zoukankan      html  css  js  c++  java
  • 2020ICPC上海 C题(数位dp, 记忆化搜索)

    先复习了下之前做的数位DP又做了道新题才看的这道题,对我来说还是一种新类型,涉及到非线性计算,之前做的都是形如 (dp[x]-dp[y])这样的只用处理一个上限做下差即可。一开始想分别枚举 (x)(y)中最高位 (1)的位置,计算符合要求的组合数目,但是一旦两个数的最高位 (1)是上限的时候感觉处理起来会很麻烦,需要分很多种讨论,而且情况还不好处理,容易缺漏。然后看了下题解,它是数位DP的思想加上记忆化搜索,它直接枚举最高位 (1)的位置,然后计算有多少种组合满足要求。状态数组为 (dp[bit][is\_1][is\_2][ok]),第一维代表枚举的位数,第二、三维代表两个数的第 (bit)位是否被锁定,如果被锁定则该位取值不能大于原数该位的值,实际上是在限制这两个数不能大于原数,第四维代表两数的或运算结果在第 (bit)位是否必须为 (1)。然后记忆化搜索统计答案。

    #include<cstdio>
    #include<cstring>
    const int mod = 1e9 + 7;
    
    int T, x, y;
    int dp[35][2][2][2];
    
    inline int max(int a, int b) { return a > b ? a : b; }
    
    // ok=1代表当前枚举的两个数的第bit位的|必须为1
    int dfs(int bit, bool is_1, bool is_2, bool ok){
        if(bit == -1)  return 1;
        if(dp[bit][is_1][is_2][ok])  return dp[bit][is_1][is_2][ok];
        int temp = 0;
        // 上界
        int k1 = is_1 ? (x >> bit & 1) : 1;
        int k2 = is_2 ? (y >> bit & 1) : 1;
        //printf("%d %d %d", bit, k1, k2);
        for(int i = 0; i <= k1; ++i)
            for(int t = 0; t <= k2; ++t){
                if(i & t)  continue;
                // 此后不必要求两数之|为1,ok=0
    	    if(ok){
                    if(i | t)  temp = (temp + dfs(bit - 1, is_1 && (i == k1), is_2 && (t == k2), 0)) % mod;  
                }
                else{
                    temp = (temp + dfs(bit - 1, is_1 && (i == k1), is_2 && (t == k2), 0)) % mod;
                }
            }
        return dp[bit][is_1][is_2][ok] = temp;
    }
    
    int main(){
        scanf("%d", &T);
        while(T--){
        	int ans = 0;
            memset(dp, 0, sizeof(dp));
            scanf("%d%d", &x, &y);
            int a = x, b = y, da = -1, db = -1;
            for(; a; a >>= 1)  ++da;
            for(; b; b >>= 1)  ++db;
            for(int i = max(da, db); i >= 0; --i){
                // 因为正在统计第i位的答案,只有两数之|在第i位为1才有贡献,所以ok=1
                ans = (ans + 1LL * dfs(i, i >= da, i >= db, 1) * (i + 1)) % mod;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    
    你只有十分努力,才能看上去毫不费力。
  • 相关阅读:
    glusterfs 术语
    python 随便
    ubuntu glusterfs 配置调试
    源码生成deb包
    常用apt cli
    unexpected error ConnectionError object has no attribute
    [MFC]透明图展示
    菜鸟的mongoDB学习---(六)MongoDB 索引
    Keyboard的显示与隐藏
    HDU 4268 Alice and Bob(贪心+Multiset的应用)
  • 原文地址:https://www.cnblogs.com/214txdy/p/14146467.html
Copyright © 2011-2022 走看看