2019牛客多校赛 第七场 H Pair

2019牛客多校赛 第七场 H Pair

题意: 给出 A, B, C, 求满足 1 <= x <= A , 1 <= y <= B 中 x & y > C | x ^ y < C的对数。
其中1 <= A, B, C <= 1e9.
思路: 反向思考,先求出 x & y <= C <= x ^ y的对数总数res, A * B - res就是答案.
求res的过程可考虑数位dp。先在a,b, c分解成二进制制数,考虑其上每一位与前一位的转移状态,一共有四种。
0 ai & bi = ci = ai ^ bi, 1 is ai & bi <= ci = ai ^ bi, ai & bi = ci <= ai ^ bi, 3 is ai & bi <= ci <= ai ^ bi
然后去掉全零的答案。

AC code:

#include
using namespace std;
typedef long long ll;

int numa[32], numb[32], numc[32];
ll dp[35][4][2][2][2][2];
ll dfs(int pos, int sta, bool limita, bool limitb, bool zeroa, bool zerob){
    if(!~pos){
        return !zeroa && !zerob; //去除前导零的答案
    }
    if(~dp[pos][sta][limita][limitb][zeroa][zerob]) return dp[pos][sta][limita][limitb][zeroa][zerob];
    int upa = limita ? numa[pos] : 1;
    int upb = limitb ? numb[pos] : 1;
    ll res = 0;
    for(int i = 0; i <= upa; ++i){
        for(int j = 0; j <= upb; ++j){
            int andv = i & j, xorv = i ^ j;
            //0 ai & bi = ci = ai ^ bi, 1 is ai & bi <= ci = ai ^ bi, ai & bi = ci <= ai ^ bi, 3 is ai & bi <= ci <= ai ^ bi
            if(sta == 0){
                if(andv < numc[pos] && numc[pos] < xorv){
                    res += dfs(pos - 1, 3, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
                }else if(andv < numc[pos] && numc[pos] == xorv){
                    res += dfs(pos - 1, 1, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);   
                }else if(andv == numc[pos] && numc[pos] < xorv){
                    res += dfs(pos - 1, 2, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
                }else if(andv == numc[pos] && numc[pos] == xorv){
                    res += dfs(pos - 1, 0, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
                }
            }else if(sta == 1){
                if(numc[pos] < xorv){
                    res += dfs(pos - 1, 3, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
                }else if(numc[pos] == xorv){
                    res += dfs(pos - 1, 1, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
                }
            }else if(sta == 2){
                if(andv < numc[pos]){
                    res += dfs(pos - 1, 3, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
                }else if(andv == numc[pos]){
                    res += dfs(pos - 1, 2, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
                }
            }else{
                res += dfs(pos - 1, 3, limita && i == upa, limitb && j == upb, zeroa && i == 0, zerob && j == 0);
            }
        }
    }
    return (dp[pos][sta][limita][limitb][zeroa][zerob] = res);
}

ll solve(int a, int b, int c){
    memset(dp, -1, sizeof(dp));
    for(int i = 31; ~i; --i){
        numa[i] = ((a >> i) & 1);
        numb[i] = ((b >> i) & 1);
        numc[i] = ((c >> i) & 1);
    }
    return dfs(31, 0, 1, 1, 1, 1);
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        ll ans = (ll)a * b - solve(a, b, c);
        printf("%lld\n", ans);
    }
    return 0;
}

你可能感兴趣的:(数位dp)