习题:Daniel and Spring Cleaning(数位DP)
题目
思路
注意到异或也可以理解成为二进制下不进位的加法
容斥之后直接数位DP即可
代码
#include<iostream>
#include<cstring>
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<<calc(r,r)-2*calc(r,l-1)+calc(l-1,l-1)<<'\n';
}
return 0;
}
/*
3
3 3
*/

浙公网安备 33010602011771号