感谢 Morning_Glory 赞助
给定 , 求
.
假设, 则将所有涉及到的数字转换为 二进制 如下 ,
以 位 为例,
每个数字都要与每个数字 异或 并且对答案造成贡献,
- 当前位置为 , 对答案贡献为 .
- 当前位置为 , 对答案贡献为 .
综上该位答案为 .
观察以上序列, 发现若当前位置为 位, 则 循环节长度为 .
先来求 中 位置的答案,
则
然后 容斥 即可求出 的 .
.
#include<bits/stdc++.h>
#define reg register
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ c = getchar(), flag = -1; break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int mod = 1e9 + 7;
int L;
int R;
int Ans;
int pw[50];
int Calc(int x, int b){
return ((x+1)/pw[b+1]) * pw[b] + std::min((x+1)%pw[b+1], pw[b]);
}
void Work(){
L = read(), R = read();
Ans = 0;
for(reg int b = 0; pw[b] <= R; b ++){
int num_0 = Calc(R, b) - Calc(L-1, b), num_1 = R-L+1 - num_0;
int pluss = (2ll*num_0*num_1 % mod) * pw[b] % mod;
Ans = (1ll*pluss + Ans) % mod;
}
printf("%d
", Ans);
}
int main(){
pw[0] = 1;
for(reg int i = 1; pw[i] <= mod; i ++) pw[i] = pw[i-1] << 1;
int T = read();
while(T --) Work();
return 0;
}