• CF 1557 C. Moamen and XOR


    C. Moamen and XOR

    题目大意

    给定(n,k),要求创建一个(n)个数的数组(a),满足(0 leq a_i < 2^k),且(a_1 \,&\, a_2 \,&\, a_3 \,&\, ldots \,&\, a_n ge a_1 oplus a_2 oplus a_3 oplus ldots oplus a_n),问方案数。

    解题思路

    简单(DP)

    从高位考虑,设(dp[i])表示前(i)位满足条件的方案数,根据(n)的奇偶性,考虑与结果(i)位为(0)(1)时的转移即可。

    • (n)为奇数
      • 与结果第(i)位为(1),则异或结果也为(1),此时(dp[i] += dp[i - 1])
      • 与结果第(i)位为(0),则要使异或结果也为(0),第(i)位填法有(C_n^0 + C_n^2 + C_n^4 + ... + C_n^{n-1} = 2^{n-1}),此时(dp[i] += 2^{n-1}dp[i - 1])
      • (dp[i] = dp[i - 1] + 2^{n-1}dp[i-1])
    • (n)为偶数
      • 与结果第(i)位为(1),则异或结果为(0),剩下(i-1)位随便填,此时(dp[i] += 2^{(i-1)n})
      • 与结果第(i)位为(0),则要使异或结果也为(0),第(i)位填法有(C_n^0 + C_n^2 + C_n^4 + ... + C_n^{n - 2} = 2^{n-1} - 1),此时(dp[i] += (2^{n-1} - 1) imes dp[i - 1])(除去(C_n^n)即全为1的填法,因为此时与结果为1)
      • (dp[i] = 2^{(i-1)n} + (2^{n-1} - 1) imes dp[i-1])
    神奇的代码
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    template <typename T>
    void read(T &x) {
        int s = 0, c = getchar();
        x = 0;
        while (isspace(c)) c = getchar();
        if (c == 45) s = 1, c = getchar();
        while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        if (s) x = -x;
    }
    
    template <typename T, typename... rest>
    void read(T &x, rest&... Rest) {
        read(x);
        read(Rest...);
    }
    
    template <typename T>
    void write(T x, char c = ' ') {
        int b[40], l = 0;
        if (x < 0) putchar(45), x = -x;
        while (x > 0) b[l++] = x % 10, x /= 10;
        if (!l) putchar(48);
        while (l) putchar(b[--l] | 48);
        putchar(c);
    }
    
    const LL mo = 1e9 + 7;
    const int N = 2e5 + 8;
    
    int n, k;
    
    LL dp[N], p2[N];
    
    LL qpower(LL a, LL b){
        LL qwq = 1;
        while(b){
            if (b & 1)
                qwq = qwq * a % mo;
            a = a * a % mo;
            b >>= 1;
        }
        return qwq;
    }
    
    int main(void) {
        int kase; read(kase);
        p2[0] = 1;
        for(int i = 1; i < N; ++ i)
            p2[i] = p2[i - 1] * 2 % mo;
        for (int ii = 1; ii <= kase; ii++) {
            read(n, k);
            memset(dp, 0, sizeof(dp));
            dp[0] = 1;
            for(int i = 1; i <= k; ++ i)
                if (n & 1){
                    dp[i] = (dp[i - 1] + p2[n - 1] * dp[i - 1] % mo) % mo;
                }else{
                    dp[i] = (qpower(p2[i - 1], n) + (p2[n - 1] - 1) * dp[i - 1] % mo) % mo;
                }
            write(dp[k], '
    ');
        }
        return 0;
    }
    


  • 相关阅读:
    mybatis---demo1--(1-n)----bai
    字符流之文件读写流
    字节字符转换流
    字节缓冲流
    字节流之数据输入输出流
    字节流之文件输出流FileOutputStream
    【洛谷P3916】图的遍历
    【codevs1297】硬币 完全背包
    【codevs2205】等差数列
    【洛谷P1214】等差数列
  • 原文地址:https://www.cnblogs.com/Lanly/p/15241905.html
Copyright © 2020-2023  润新知