习题: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

*/
posted @ 2020-08-24 16:42  loney_s  阅读(114)  评论(0)    收藏  举报