zoukankan      html  css  js  c++  java
  • codeforce刷题

    codeforce 1332D Walk on Matrix

    题目: https://vjudge.net/problem/CodeForces-1332D

    题解

    切入点是找出题目所给算法的错误之处,也就是每一次取最优解,但结果可能不是最优解的情况。比如:

    111  100    0
    11   111   11
    

    按照给出的算法,(dp[2][2] = 100_{(2)} = 4),而(dp[2][3] = 0_{(2)} = 0),也就是在(dp)过程中,每次都取了最高位为1作为当前最优解。实际上,选择 (111 ightarrow 11 ightarrow 111 ightarrow 11), 得到(maxAnd = 11_{(2)} = 3)
    构造出这样的样例后,将(11_{(2)})换成(k)的二进制,写出矩阵就行啦

    const int MAXN = 200005;
    
    int get(int x, int op) {
        int t = 0, tp = x;
        while(tp) {
            tp >>= 1;
            t++;
        }
        if (op == 0) {
            return (1 << t) + (~x & ((1 << t) - 1));
        }
        else {
            return (1 << t) + x;
        }
    }
    
    int main() {
    
        int k; cin >> k;
    
        int a[2][3] = {{get(k, 1), get(k, 0), 0}, {k, get(k, 1), k}};
        cout << "2 3" << endl;
        myfor(i, 0, 2) {
            myfor(j, 0, 3) printf("%d ", a[i][j]);
            cout << endl;
        }
        return 0;
    }
    
    

    整麻烦了,看这位大佬的构造:https://blog.csdn.net/weixin_42431507/article/details/105236247?>

    CodeForces 1329B Dreamoon Likes Sequences

    给两个数(d(1 <= d <= 10^9))(m(1 <= m <= 10^9)),问有多少种满足如下条件的(a)序列?方案数要模上(m)

    • (a)序列的长度为(n) ((1<= n <= d))
    • (1 <= a_1 < a_2 < ··· < a_n <= d)
    • (b[i] = a_1 igoplus a_2 igoplus ··· igoplus a_i)(b[1] = a_1)。满足(b[1] < b[2] < ··· < b[n])

    题解

    (d)(m) 都超级大,又涉及异或运算,考虑从二进制入手。满足(a)的递增比较简单,重点是怎么确保(b)的递增。有 (b[1] = a_1)(b[2] = a_1 igoplus a_2)(a_2 > a_1),那么(b[2] > b[1])说明(a_2)的二进制长度大于(a_1)的二进制长度。以此递推,可以发现,(a)序列中元素的二进制长度是递增的,所以(a)的元素个数最多30个((2^{30} > 10^9)).
    将二进制长度相同的数划分为1组(比如4,5,6,7的二进制长度都是3,归为一组),然后每组只能取一个数,求方案数。举例来说:(d = 5),共有三组:((1))((2, 3))((4, 5))。令(ans_n :=)表是长度为(n)且符合条件的(a)序列个数,根据组合数学的知识可得 (ans_1 = 5)(ans_2 = 1 * 2 + 1 * 2 + 2 * 2 = 8)(ans_3 = 1 * 2 * 2 = 4)。求得总的方案数: (ans = ans_1 + ans_2 + ans_3 = 17)
    最后,思考怎么(code)。硬搜肯定复杂度超了,令(dp[i][j]:=)(i)个组选择(j)个数的方案数,有

    [ dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] * cnt[i] ]

    注意爆int

    int bit_length(int x) {
        int t = 0;
        while(x) {t++, x >>= 1; }
        return t;
    }
    
    void Inite() {
        memset(cnt, 0, sizeof(cnt));
        memset(dp, 0, sizeof(dp));
    
        group = bit_length(d);
        for (int i = 1; i < group; ++i) cnt[i] = 1 << (i - 1), d -= cnt[i];
        cnt[group] = d;
    
        //for (int i = 1; i <= group; ++i) printf("%d ", cnt[i]);
        //printf("
    ");
    }
    
    void Solve() {
        cin >> d >> mod;
    
        Inite();
    
        for (int i = 1; i <= group; ++i) for (int j = 1; j <= i; ++j) {
            if (j == 1) dp[i - 1][j - 1] = 1;
            dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1] * cnt[i] % mod) % mod;
        }
    
        long long ans = 0;
        for (int i = 1; i <= group; ++i) ans = (ans + dp[group][i]) % mod;
        cout << ans << endl;
    }
    
  • 相关阅读:
    Android 走向MD的配色风格
    Android热点回顾第六期
    C#集合类:动态数组、队列、栈、哈希表、字典(转)
    Google Chrome默认字体设置(Win)
    C# Socket的粘包处理(转)
    设计模式原则总结--读《大话设计模式》有感 <转>
    C#设计模式学习笔记-单例模式(转)
    C# 编写Windows Service(windows服务程序)
    C# 获取农历日期
    C# 中怎么将string转换成int型
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/12654313.html
Copyright © 2011-2022 走看看