zoukankan      html  css  js  c++  java
  • 题解 P5401 [CTS2019]珍珠

    蒟蒻语

    这题太玄学了,蒟蒻写篇题解来让之后复习 = =

    蒟蒻解

    假设第 (i) 个颜色有 (cnt_i) 个珍珠。

    (sumlimits_{i=1}^{n} leftlfloorfrac{cnt_i}{2} ight floor ge m)

    (sumlimits_{i=1}^{n} cnt_i - cnt_i mod 2 ge 2m)

    (n - sumlimits_{i=1}^{n} cnt_i mod 2 ge 2m)

    (sumlimits_{i=1}^{n} cnt_i mod 2 le n-2m)

    (cnt) 数组中的奇数个数小于等于 (n-2m)

    如果 (n-2mge d),那么答案显然为 (d^n) (没有任何限制了)

    如果 (n-2mle 0) 那么答案为 (0)

    (g = n - 2 m)

    (odd_i) : (cnt) 数组中恰好 (i) 个奇数的方案数

    (f_i) : (cnt) 数组中钦定 (i) 个奇数的方案数

    [ans = sumlimits_{i=0}^{g} odd_i ]

    [f_x=sumlimits_{i=x}^{d} C_i^x odd_i Leftrightarrow odd_x=sumlimits_{i=x}^{d} (-1)^{i-x} C_i^x f_i ]

    所以考虑通过算出 f 来算出 odd 数组, 从而求得答案。

    [f_i=n!(C_{D}^{i})(sumlimits_{i=0} frac{x^i}{i!})^{D-i}(sumlimits_{i=0} [i mod 2 = 1] frac{x^i}{i!})^i [x^n] ]

    [f_i=n!(C_{D}^{i})e^{x(D-i)} (frac{e^{x} - e^{-x}}{2})^{i}[x^n] ]

    二项式展开:

    [f_i=n!(C_{D}^{i})frac{1}{2^i} sumlimits_{j=0}^{i} C_i^j e^{x(D-i)} e^{jx} (-e^{-x})^{i-j} [x^n] ]

    [f_i=n!(C_{D}^{i})frac{1}{2^i} sumlimits_{j=0}^{i} (-1)^j C_i^j e^{x(D-i)} e^{(i-j)x} e^{-xj} [x^n] ]

    [f_i=n!(C_{D}^{i})frac{1}{2^i} sumlimits_{j=0}^{i} (-1)^j C_i^j e^{x(D-2j)} [x^n] ]

    [f_i=n!(C_{D}^{i})frac{1}{2^i} sumlimits_{j=0}^{i} (-1)^j C_i^j frac{(D-2j)^n}{n!} ]

    [f_i=n!(C_{D}^{i})frac{1}{2^i} sumlimits_{j=0}^{i} (-1)^j frac{i!}{j!(i-j)!} frac{(D-2j)^n}{n!} ]

    [f_i=(C_{D}^{i})frac{1}{2^i} sumlimits_{j=0}^{i} (-1)^j frac{i!}{j!(i-j)!} (D-2j)^n ]

    [P_i=(-1)^i frac{1}{i!} (D-2i)^n ]

    [f_i=i!(C_{D}^{i})frac{1}{2^i} sumlimits_{j=0}^{i} P_j frac{1}{(i-j)!} ]

    [这就是个卷积式了!然后就求出了 f_i ]

    [odd_x=sumlimits_{i=x}^{d} (-1)^{i-x} C_i^x f_i ]

    [odd_x=(-1)^x sumlimits_{i=x}^{d} (-1)^i frac{i!}{x!(i-x)!} f_i ]

    [odd_x=frac{1}{x!}(-1)^x sumlimits_{i=x}^{d} (-1)^i frac{i!}{(i-x)!} f_i ]

    [G_i =f_i(-1)^ii! ]

    [odd_x=frac{1}{x!}(-1)^x sumlimits_{i=x}^{d} frac{1}{(i-x)!} G_i ]

    [odd_x=frac{1}{x!}(-1)^x sumlimits_{i=x}^{d} frac{1}{(i-x)!} G_i ]

    [odd_x=frac{1}{x!}(-1)^x sumlimits_{i=0}^{d-x} frac{1}{i!} G_{i+x} ]

    [翻转 odd 和 G ]

    [odd_{d-x}=frac{1}{x!}(-1)^x sumlimits_{i=0}^{d-x} frac{1}{i!} G_{d-x-i} ]

    然后再卷一卷答案就求出来了!!!

    蒟蒻码

    #include<bits/stdc++.h>
    using namespace std;
    #define L(i, j, k) for(int i = (j), i##E = (k); i <= i##E; i++) 
    #define R(i, j, k) for(int i = (j), i##E = (k); i >= i##E; i--) 
    #define ll long long 
    #define db double
    #define make_pair mp 
    #define first x
    #define second y
    #define pb push_back
    #define mod 998244353
    #define iG 3
    #define invG 332748118
    #define sz(x) (int)(x.size())
    const int N = 4e5 + 7;
    int qpow(int x, int y) {
        if(x == 0) return 0;
        int res = 1;
        for(; y; x = 1ll * x * x % mod, y >>= 1) if(y & 1) res = 1ll * res * x % mod;
        return res;
    }
    int ny(int x) { return qpow(x, mod - 2); }
    int pp[N];
    void fft(int *f, int len, int flag) {
        for(int i = 0; i < len; i++) if(i < pp[i]) swap(f[pp[i]], f[i]);
        for(int i = 2; i <= len; i <<= 1) {
            int l = (i >> 1);
            for(int j = 0; j < len; j += i) {
                int ch = qpow(flag == 1 ? iG : invG, (mod - 1) / i), now = 1;
                for(int k = j; k < j + l; k++) {
                    int ta = f[k], tb = 1ll * f[k + l] * now % mod;
                    f[k] = (ta + tb) % mod;
                    f[k + l] = (ta - tb + mod) % mod;
                    now = 1ll * now * ch % mod;
                }
            }
        }
        if(flag == -1) {
            int invn = ny(len);
            for(int i = 0; i < len; i++) f[i] = 1ll * f[i] * invn % mod;
        }
    }
    int n, m, d, g, ans, f[N], P[N], ml;
    int jc[N], njc[N];
    int C(int x, int y) { return 1ll * jc[x] * njc[y] % mod * njc[x - y] % mod; }
    int main() {
        scanf("%d%d%d", &d, &n, &m);
        if(n - 2 * m < 0) return printf("0
    "), 0;
        if(n - 2 * m >= d) return printf("%d
    ", qpow(d, n)), 0;
        jc[0] = njc[0] = 1;
        L(i, 1, d) jc[i] = 1ll * jc[i - 1] * i % mod, njc[i] = ny(jc[i]);
        for(ml = 1; ml <= d * 2; ml <<= 1);
        L(i, 0, d) P[i] = 1ll * qpow((d - 2 * i + mod) % mod, n) * (i % 2 == 0 ? 1 : mod - 1) % mod * njc[i] % mod, f[i] = njc[i];
        for(int i = 0; i < ml; i++) pp[i] = ((pp[i >> 1] >> 1) | ((i & 1) * (ml >> 1)));
        fft(P, ml, 1), fft(f, ml, 1);
        for(int i = 0; i < ml; i++) f[i] = 1ll * P[i] * f[i] % mod;
        fft(f, ml, -1);
        for(int i = d + 1; i < ml; i++) f[i] = 0;
        int now = 1;
        L(i, 0, d) f[i] = 1ll * f[i] * now % mod * jc[d] % mod * njc[d - i] % mod, now = 1ll * now * 499122177 % mod;
        L(i, 0, d) f[i] = 1ll * f[i] * (i % 2 == 0 ? 1 : mod - 1) % mod * jc[i] % mod;
        reverse(f, f + d + 1);
        for(int i = 0; i < ml; i++) P[i] = 0;
        L(i, 0, d) P[i] = njc[i];
        fft(f, ml, 1), fft(P, ml, 1);
        for(int i = 0; i < ml; i++) f[i] = 1ll * f[i] * P[i] % mod;
        fft(f, ml, -1);
        reverse(f, f + d + 1);
        L(i, 0, d) f[i] = 1ll * f[i] * (i % 2 == 0 ? 1 : mod - 1) % mod * njc[i] % mod;
        g = n - 2 * m;
        L(i, 0, g) (ans += f[i]) %= mod;
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    PRISM概率模型检测器初使用--骰子模型(改进版)
    什么是P问题、NP问题和NPC问题
    kali linux进行arp欺骗和dos攻击
    java log日志的输出。
    sublime text3输入中文的问题.
    java 正则表达式匹配字符串
    python tornado+mongodb的使用
    jasper3
    jasper2
    jasper
  • 原文地址:https://www.cnblogs.com/zkyJuruo/p/13822584.html
Copyright © 2011-2022 走看看