也许更好的体验
D
e
s
c
r
i
p
t
i
o
n
\mathcal{Description}
Description
给定L,R,求
∑
i
=
L
R
x
o
r
∑
i
=
L
R
\sum_{i=L}^{R}xor\sum_{i=L}^{R}
∑i=LRxor∑i=LR
答案对1000000007取模
L
,
R
<
=
1
0
9
L,R<=10^9
L,R<=109
S
o
l
u
t
i
o
n
\mathcal{Solution}
Solution
对于有异或的题目要记住这点
每个二进制位是独立计算答案的
我们只需知道
[
L
,
R
]
[L,R]
[L,R]中所有数在每个位上的情况:有多少
0
0
0多少
1
1
1
只有
1
1
1^
0
0
0的结果为
1
1
1,统计出每个为上的
1
1
1,
0
0
0的个数,用当前位的值乘以
1
1
1的个数再乘以
0
0
0的个数即可
对于每个二进制位上的0和1出现情况
如第
3
3
3位
000
001
010
011
100
101
110
111
每
2
4
2^4
24出现
2
3
2^3
23个
0
0
0和
1
1
1
不难发现每
2
n
+
1
2^{n+1}
2n+1个数在第n位出现
2
n
2^n
2n个
0
0
0和
1
1
1
由于对数会被异或两次 i^j, j^i,所以计算时要乘以
2
2
2
即
a
n
s
=
(
a
n
s
+
2
∗
z
e
r
o
[
i
]
∗
o
n
e
[
i
]
∗
2
i
)
ans=(ans+2*zero[i]*one[i]*2^i)%mod;
ans=(ans+2∗zero[i]∗one[i]∗2i)
0
0
0和
1
1
1的计算
用一个简单的容斥即可
对于第n位
R中包含的
2
n
+
1
2^{n+1}
2n+1的个数减去L中包含的
2
n
+
1
2^{n+1}
2n+1个数加上
R
%
2
n
+
1
R\%2^{n+1}
R%2n+1中的个数减去
L
%
2
n
+
1
L\%2^{n+1}
L%2n+1中的个数
注意计算的起点为
0
0
0,即求的区间是
[
0
,
R
]
−
[
0
,
L
−
1
]
[0,R]-[0,L-1]
[0,R]−[0,L−1]
处理看代码吧
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年06月10日 星期一 07时59分11秒
*******************************/
#include <cstdio>
#include <fstream>
#include <cstring>
using namespace std;
const int mod = 1000000007;
const int maxn = 55;
int n,T,t,l,r;
long long ans;
long long zero[maxn],one[maxn],mi[maxn];
int main()
{
scanf("%d",&T);
mi[0]=1;
for (int i=1;i<=31;++i) mi[i]=mi[i-1]<<1;
while (T--){
scanf("%d%d",&l,&r);
memset(one,0,sizeof(one));
memset(zero,0,sizeof(zero));
ans=0;
for (int i=0;mi[i]<=r;++i){
one[i]=((r+1)/mi[i+1]-l/mi[i+1])*mi[i];//R中包含的2^{n+1}的个数减去L中包含的2^{n+1}个数
zero[i]=one[i];
//加上R%2^{n+1}中的个数
if (r+1>mi[i+1]){
t=(r+1)%mi[i+1];
if (t>mi[i]) one[i]+=t-mi[i],zero[i]+=mi[i];
else zero[i]+=t;
}
else if (r+1<mi[i+1]){
if (r+1>mi[i]) one[i]+=r+1-mi[i],zero[i]+=mi[i];
else zero[i]-=r+1;
}
//减去L%2^{n+1}中的个数
if (l>mi[i+1]){
t=l%mi[i+1];
if (t>mi[i]) one[i]-=t-mi[i],zero[i]-=mi[i];
else zero[i]-=t;
}
else if (l<mi[i+1]){
if (l>mi[i]) one[i]-=l-mi[i],zero[i]-=mi[i];
else zero[i]-=l;
}
ans=(ans+2ll*zero[i]*one[i]%mod*mi[i])%mod;
}
printf("%lld\n",ans);
}
return 0;
}