【GDOI2018模拟7.6】吃干饭
2017-07-06 21:55
369 查看
Description
求区间[l,r]中的数任意互相异或之后有多少种可能的结果l<=r<=1e18,数据组数<=100
Solution
这种题一眼线性基啦~虽然我并不太熟练,还自己推了一遍插入
这样直接暴力做有50分
然后打了个表发现了一个规律:
首先l一定会在线性基中,
然后我们知道了线性基中的最后一个数,想要快速找出线性基中的下一个数
假设当前的数的二进制表示是 10100,那么接下来的会是
10100
10101
10110
11000
11100
也就是每次找当前最后一个数中,从最低位起第一个当前位为0且线性基为空的位置
然后这一位是1,后面就都是0,并插入到这一位的线性基中
感性理解一下好像没什么毛病
那就直接模拟这个过程就好了,复杂度O(T log^2 L)
Code
#include <cstdio> #include <cstring> #include <algorithm> #define fo(i,a,b) for(ll i=a;i<=b;i++) #define fd(i,a,b) for(ll i=a;i>=b;i--) using namespace std; typedef long long ll; ll l,r,ans,a[61],mi[61]; int main() { freopen("A.in","r",stdin); freopen("A.out","w",stdout); int ty; mi[0]=1;fo(i,1,60) mi[i]=mi[i-1]*2; for(scanf("%d",&ty);ty;ty--) { scanf("%lld%lld",&l,&r); if (!l&&!r) { printf("1\n"); continue; } fo(i,0,60) a[i]=0; ll x=l;ans=2;if (!x) x=1; fd(i,60,0) if (x&mi[i]) {a[i]=x;break;} while (x<r) { int now=61; fo(i,0,60) if (!a[i]&&!(x&mi[i])) { now=i; break; } if (now>60) break; fo(i,0,now-1) if (x&mi[i]) x-=mi[i]; x+=mi[now];a[now]=x; if (x<=r) ans=ans*2; } printf("%lld\n",ans); } }
相关文章推荐
- 【JZOJ 5204】【GDOI2018模拟7.6】吃干饭
- 【GDOI2018模拟7.6】仰望星空
- 【JZOJ 5205】【GDOI2018模拟7.6】仰望星空
- 2018.02.05【GDOI2018】模拟C组——Multiset
- 【jzoj5239】【GDOI2018模拟8.7】【图的异或】【线性基】
- 【JZO5271】【GDOI2018模拟8.14】神奇的救火现场
- JZOJ 5221. 【GDOI2018模拟7.10】A
- 2018.01.27【GDOI2018】模拟C组——无线网络
- 【JZOJ 5241】【GDOI2018模拟8.8】苹果和雪梨
- 【GDOI2018模拟7.10】C
- 【JZOJ5260】【GDOI2018模拟8.12】区间第k小
- 【GDOI2018模拟9.16】幽雅的绽放吧,墨染之樱
- 【JZOJ 5215】【GDOI2018模拟7.9】组合数问题
- jzoj5220 【GDOI2018模拟7.10】C (双序列dp)
- 【JZOJ5262】【GDOI2018模拟8.12】树
- 【jzoj5215】【BZOJ4870】【Shoi2017】【GDOI2018模拟7.9】【组合数问题】【矩阵快速幂】
- 【JZOJ 5229】【GDOI2018模拟7.14】小奇的糖果
- 2018.02.02【GDOI2018】模拟C组——最大配对
- 【jzoj5238】【GDOI2018模拟8.7】【的士碰撞】
- 【JZOJ5250】【GDOI2018模拟】质数(数论)