2019牛客暑期多校训练营(第七场)H.Pair(数位dp)

题意:给你三个数A,B,C 现在要你找到满足  A and B >C 或者 A 异或 B < C 的对数。

思路:我们可以走对立面 把既满足 A and B <= C 也满足 A 异或 B >= C的个数用数位dp统计出来 最后用A*B减去即可

#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1.0);
const int N = 1e6+7;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
typedef long long ll;
const ll mod = 1e7+9;
int bita[50],bitb[50],bitc[50];
ll dp[50][2][2][2][2];
ll dfs(int len,int maxa,int maxb,int ad,int xo){
    if(!len) return 1;
    if(dp[len][maxa][maxb][ad][xo]>=0) return dp[len][maxa][maxb][ad][xo];
    ll res=0;
    int upa=maxa?bita[len]:1; int upb=maxb?bitb[len]:1;
    for(int i=0;i<=upa;i++)
        for(int j=0;j<=upb;j++){
            if((ad&&(i&j)>bitc[len])||xo&&(i^j)<bitc[len]) continue;
            res+=dfs(len-1,maxa&&(i==upa),maxb&&(j==upb),
            ad&&((i&j)==bitc[len]),xo&&((i^j)==bitc[len]));
        }
    dp[len][maxa][maxb][ad][xo]=res;
    return res;
}
ll solve(ll A,ll B,ll C){
    int lena,lenb,lenc;
    lena=lenb=lenc=0;
    while(A){bita[++lena]=A&1; A>>=1;}
    while(B){bitb[++lenb]=B&1; B>>=1;}
    while(C){bitc[++lenc]=C&1; C>>=1;}
    int len=max(lena,max(lenb,lenc));
    return dfs(len,1,1,1,1);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int t; cin>>t;
    while(t--){
        memset(dp,-1,sizeof(dp));
        memset(bita,0,sizeof(bita));
        memset(bitb,0,sizeof(bitb));
        memset(bitc,0,sizeof(bitc));
        ll A,B,C; cin>>A>>B>>C;
        ll ans=solve(A,B,C);
        ans-=max(0LL,A-C+1);
        ans-=max(0LL,B-C+1);
        cout<<A*B-ans<<endl;
    }
}

 

 

posted @ 2019-08-22 14:40  WAKBGAN  阅读(177)  评论(0编辑  收藏  举报