题目
题意
求区间 [ l , r ] [l,r] [l,r] ( r < 1 e 9 ) (r<1e9) (r<1e9) 里的二元对数 ( a , b ) (a,b) (a,b),满足 a + b = a x o r b a+b=a \ xor \ b a+b=a xor b
思路
可以发现是个数位dp(xjb dfs)题
一维的时候
f
(
[
l
,
r
]
)
=
f
(
[
0
,
r
]
)
−
f
(
[
0
,
l
−
1
]
)
f([l,r])=f([0,r])-f([0,l-1])
f([l,r])=f([0,r])−f([0,l−1])
此时考虑把维度扩展到二维,联想二维坐标轴
f
(
[
x
1
,
y
1
]
,
[
x
2
,
y
2
]
)
=
f
(
[
0
,
0
]
,
[
x
2
,
y
2
]
)
−
f
(
[
0
,
0
]
,
[
x
1
−
1
,
y
1
]
)
−
f
(
[
0
,
0
]
,
[
x
1
,
y
1
−
1
]
)
+
f
(
[
0
,
0
]
,
[
x
1
−
1
,
y
1
−
1
]
)
f([x1,y1],[x2,y2])=f([0,0],[x2,y2])-f([0,0],[x1-1,y1])-f([0,0],[x1,y1-1])+f([0,0],[x1-1,y1-1])
f([x1,y1],[x2,y2])=f([0,0],[x2,y2])−f([0,0],[x1−1,y1])−f([0,0],[x1,y1−1])+f([0,0],[x1−1,y1−1])
然后考虑用数位求
f
(
x
,
y
)
f(x,y)
f(x,y):
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]第
i
i
i位,
a
a
a是否已经小于
x
x
x,
b
b
b是否以及小于
y
y
y, 的种类数。
然后dfs分类讨论,考虑当前二进制位置上,
x
,
y
x,y
x,y的值,以及
j
,
k
j,k
j,k的值,并且保证
a
,
b
a,b
a,b当前位置最多只有一个取1
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define SZ(a) (int)a.size()
const int MXN = 1e6+5;
LL dp[50][2][2]; //pos[i],a<r? b<r?
vector<int>la,lb;
LL dfs(LL p,LL sta,LL stb){ //0:contain,1:notcontain
if(dp[p][sta][stb]!=-1) return dp[p][sta][stb];
if(p==35) return 1;
LL re=0;
if(sta==1&&stb==1) re=re+dfs(p+1,1,1)+dfs(p+1,1,1)+dfs(p+1,1,1);
if(sta==1&&stb==0) {
if(lb[p]==1) {
re=re+dfs(p+1,1,1)+dfs(p+1,1,0)+dfs(p+1,1,1);
}
if(lb[p]==0){
re=re+dfs(p+1,1,0)+dfs(p+1,1,0);
}
}
if(sta==0&&stb==1) {
if(la[p]==1) {
re=re+dfs(p+1,1,1)+dfs(p+1,0,1)+dfs(p+1,1,1);
}
if(la[p]==0){
re=re+dfs(p+1,0,1)+dfs(p+1,0,1);
}
}
if(sta==0&&stb==0){
if(la[p]==0&&lb[p]==0){
re=re+dfs(p+1,0,0);
}
if(la[p]==1&&lb[p]==0){
re=re+dfs(p+1,0,0)+dfs(p+1,1,0);
}
if(la[p]==0&&lb[p]==1){
re=re+dfs(p+1,0,0)+dfs(p+1,0,1);
}
if(la[p]==1&&lb[p]==1){
re=re+dfs(p+1,0,1)+dfs(p+1,1,0)+dfs(p+1,1,1);
}
}
return dp[p][sta][stb]=re;
}
LL f(LL a,LL b){
memset(dp,-1,sizeof(dp));
la.clear(),lb.clear();
LL ta=a;
while(ta) la.push_back(ta%2),ta/=2;
while(SZ(la)<35) la.push_back(0);
reverse(la.begin(),la.end());
LL tb=b;
while(tb) lb.push_back(tb%2),tb/=2;
while(SZ(lb)<35) lb.push_back(0);
reverse(lb.begin(),lb.end());
return dfs(1,0,0);
}
int MAIN(int avg){
LL l,r;scanf("%lld%lld",&l,&r);
cout<<f(r,r)+f(l-1,l-1)-f(l-1,r)-f(r,l-1)<<'\n';
return 0;
}
int main(){
int ca;cin>>ca;for(int i=1;i<=ca;i++) MAIN(i);
return 0;
}