CF1245 F.Daniel and Spring Cleaning【数位DP】

题目链接:CF1245 F.Daniel and Spring Cleaning

题意:给你一个区间,问区间内有多少对数满足a^b==a+b;([a,b]和[b,a]是两个答案)

分析:由题意知道是求a&b==0的对数,既然是位运算就可以转化成二进制下的数位DP,1e9不到30位;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int s1[35],s2[35];
ll dp[35][2][2];
ll dfs(int pos,bool lim1,bool lim2)//是否要取上界
{
    if(pos==0) return 1;
    if(~dp[pos][lim1][lim2]) return dp[pos][lim1][lim2];
    int mx1,mx2;mx1=mx2=1;
    if(lim1) mx1=s1[pos];
    if(lim2) mx2=s2[pos];
    ll res=0;
    for(int i=0;i<=mx1;i++) for(int j=0;j<=mx2;j++)
        if((i&j)==0) res+=dfs(pos-1,lim1&&i==mx1,lim2&&j==mx2);
    return dp[pos][lim1][lim2]=res;
}
ll cal(ll a,ll b)
{
    if(a<0 || b<0) return 0;
    memset(dp,-1,sizeof(dp));
    for(int i=1;i<32;i++) s1[i]=a&1,a>>=1,s2[i]=b&1,b>>=1;
    return dfs(31,1,1);
}
ll rua()
{
    ll a,b;scanf("%lld%lld",&a,&b);
    return cal(b,b)-2*cal(a-1,b)+cal(a-1,a-1);
}
int main()
{
    int t;scanf("%d",&t);
    while(t--) printf("%lld\n",rua());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43813163/article/details/102875604