CF1245F。ダニエルと春の大掃除【数位DP】

タイトルリンク:CF1245F。ダニエルと春の大掃除

質問の意味:間隔を与え、間隔内の対数がa ^ b == a + bを満たす数を尋ねます;([a、b]と[b、a]は2つの答えです)

分析:質問の意味によると、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