题意求
∑
i
=
0
x
∑
j
=
[
i
=
0
]
y
[
i
&
j
=
0
]
⌊
l
o
g
2
(
i
+
j
)
+
1
⌋
\sum_{i=0}^{x}\sum_{j=[i=0]}^{y} [i\& j=0]\lfloor log_2(i+j)+1 \rfloor
i=0∑xj=[i=0]∑y[i&j=0]⌊log2(i+j)+1⌋
题解:很容易想到枚举i+j的位数,然后求再范围内的
[
i
&
j
]
[i\&j]
[i&j]的(i,j)对。考虑用数位dp。记
f
[
k
]
[
l
1
]
[
l
2
]
f[k][l1][l2]
f[k][l1][l2]表示0-k为i&j=0的个数。用数位dp计算就行。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e9+7;
ll f[50][2][2],ans;
int a[50],b[50],cnt1,cnt2,x,y,cas;
inline void init(){
cnt1=0;cnt2=0;ans=0;
int t=x;
memset(a,0,sizeof a);
memset(b,0,sizeof b);
while(t){
a[cnt1++]=t%2;
t/=2;
}
t=y;
while(t){
b[cnt2++]=t%2;
t/=2;
}
memset(f,-1,sizeof f);
}
ll dfs(ll k, int l1,int l2){// 表示是否被限制
if(k==-1) return 1;
if(f[k][l1][l2]!=-1) return f[k][l1][l2];
ll &v=f[k][l1][l2];
v=0;//注意记得从-1改成0
int up1=(l1)?a[k]:1;//上限
int up2=(l2)?b[k]:1;//上限
for(int i=0;i<=up1;i++){
for(int j=0;j<=up2;j++){
if((i&j)==0)
v=(v+dfs(k-1,i==up1&&l1,j==up2&&l2))%M;
}
}
return v;
}
int main(){
scanf("%d",&cas);
while(cas--){
scanf("%d%d",&x,&y);
init();
//枚举(i+j)的位数
for(int i=0;i<max(cnt1,cnt2);i++){
ll res=0;
if(i<cnt1){
res=(res+dfs(i-1,i==(cnt1-1),i>=cnt2))%M;
}
if(i<cnt2){
res=(res+dfs(i-1,i>=cnt1,i==(cnt2-1)))%M;
}
ans=(ans+res*(i+1))%M;
}
printf("%lld\n",ans);
}
return 0;
}