题目
传送门
思路
比较有意思的转换
考虑如果要满足\(a+b=a\oplus b\)
那么定然a和b的每一位一定满足\(a\&b==1\)
之后按数位DP的套路来做即可
考虑对式子进行一个容斥
\(\sum_{a=l}^r\sum_{b=l}^{r}[a+b=a\oplus b]=\sum_{a=0}^{r}\sum_{b=0}^{r}[a+b=a\oplus b]-2*\sum_{a=0}^{l-1}\sum_{b=0}^{r}[a+b=a\oplus b]+\sum_{a=0}^{l-1}\sum_{b=0}^{l-1}[a+b=a\oplus b]\)
这样就可以排除下界的影响
代码
#include
#include
using namespace std;
int t;
int l,r;
int limitx[100],limity[100];
int lenx,leny;
long long dp[100][2][2];
void divide(long long val,int *limit,int &len)
{
len=0;
while(val)
{
limit[len++]=(val&1);
val>>=1;
}
len--;
}
long long solve(long long pos,int limx,int limy)
{
if(pos==-1)
return 1;
if(dp[pos][limx][limy]!=-1)
return dp[pos][limx][limy];
dp[pos][limx][limy]=0;
for(int i=0;i<=(limx?limitx[pos]:1);i++)
for(int j=0;j<=(limy?limity[pos]:1);j++)
if(!(i&j))
dp[pos][limx][limy]+=solve(pos-1,limx&&i==limitx[pos],limy&&j==limity[pos]);
return dp[pos][limx][limy];
}
long long calc(long long x,long long y)
{
memset(dp,-1,sizeof(dp));
memset(limitx,0,sizeof(limitx));
memset(limity,0,sizeof(limity));
if(y==-1||x==-1)
return 0;
divide(x,limitx,lenx);
divide(y,limity,leny);
return solve(max(lenx,leny),1,1);
}
int main()
{
cin>>t;
for(int i=1;i<=t;i++)
{
cin>>l>>r;
cout<