Loading

「题解」[UOJ 450]「集训队作业 2018」复读机

一台复读机的 EGF \(F(x)=\displaystyle\sum_{n\ge 0}[d|n]\frac{x^n}{n!}\)

则有答案的 EGF \(G(x)=F^k(x)\)。我们要求的就是 \(\left[\dfrac{x^n}{n!}\right]G(x)\)

  • \(d=1\)

此时有

\[\begin{align*} F(x)&=\sum_{n\ge 0}\frac{x^n}{n!} \\ &=e^x \end{align*} \]

\[\begin{align*} G(x)&=F^k(x) \\ &=e^{kx} \end{align*} \]

\(\left[\dfrac{x^n}{n!}\right]G(x)=k^n\)

时间复杂度 \(\Theta(\log n)\)

  • \(d=2\)

此时有

\[\begin{align*} F(x)&=1+\frac{x^2}{2!}+\frac{x^4}{4!}+\frac{x^6}{6!}+\cdots \\ &=\frac{1}{2}\left(\sum_{n\ge 0}\frac{x^n}{n!}+\sum_{n \ge 0}(-1)^n\frac{x^n}{n!}\right) \\ &=\frac{e^x+e^{-x}}{2} \end{align*} \]

\[\begin{align*} G(x)&=\frac{1}{2^k}\cdot\left(e^x+e^{-x}\right)^k \\ &=\frac{1}{2^k}\cdot\sum_{i=0}^{k}\binom{k}{i}e^ie^{-(k-i)x} \\ &=\frac{1}{2^k}\cdot\sum_{i=0}^{k}\binom{k}{i}e^{(2i-k)x} \end{align*} \]

\(\left[\dfrac{x^n}{n!}\right]G(x)=\dfrac{1}{2^k}\displaystyle\sum_{i=0}^{k}\binom{k}{i}(2i-k)^n\)

时间复杂度 \(\Theta(k \log n)\)

  • \(d=3\)

由单位根反演可得(以下记 \(w=w_3\)):

\[\begin{align*} F(x)&=\sum_{n \ge 0}[3|n]\frac{x^n}{n!} \\ &=\frac{1}{3}\sum_{n\ge 0}(w^{0n}+w^{1n}+w^{2n})\frac{x^n}{n!} \\ &=\frac{1}{3}\left(e^x+e^{wx}+e^{w^2x}\right) \end{align*} \]

用二项式定理扩展到多项式的形式进行展开得:

\[\begin{align*} G(x)&=\frac{1}{3^k}\cdot\left(e^x+e^{wx}+e^{w^2x}\right)^k \\ &=\frac{1}{3^k}\cdot\sum_{i=0}^{k}\sum_{j=0}^{k-i}\binom{k}{i,j,k-i-j}e^{ix}e^{jwx}e^{(k-i-j)w^2x} \\ &=\frac{1}{3^k}\cdot\sum_{i=0}^{k}\sum_{j=0}^{k-i}\binom{k}{i,j,k-i-j}e^{\left[i+jw+\left(k-i-j\right)w^2\right]x} \end{align*} \]

其中 \(\displaystyle\binom{k}{i,j,k-i-j}\)多重组合数

\(\left[\dfrac{x^n}{n!}\right]G(x)=\dfrac{1}{3^k}\displaystyle\sum_{i=0}^{k}\sum_{j=0}^{k-i}\binom{k}{i,j,k-i-j}\left[i+jw+\left(k-i-j\right)w^2\right]^n\)

时间复杂度 \(\Theta(k^2 \log n)\)

代码
#include <bits/stdc++.h>

#define int unsigned long long

using namespace std;

const int N = 1e3, P = 19491001;

int n, k, d, ans, w, fac[N + 10], ifac[N + 10];

void InitC() {
    fac[0] = fac[1] = ifac[0] = ifac[1] = 1;
    for (int i = 2; i <= N; i++) ifac[i] = (P - P / i) * ifac[P % i] % P;
    for (int i = 2; i <= N; i++) fac[i] = fac[i - 1] * i % P, ifac[i] = ifac[i] * ifac[i - 1] % P;
}

int C(int x, int y) { return fac[x] * ifac[y] % P * ifac[x - y] % P; }
int C(int x, int y, int z) { return fac[x] * ifac[y] % P * ifac[z] % P * ifac[x - y - z] % P; }

int qpow(int a, int b) {
    int ret = 1;
    for (; b; b >>= 1, a = a * a % P) b & 1 ? ret = ret * a % P : 0;
    return ret;
}

struct OI {
    int RP, score;
} FJOI2022;

signed main() {
    FJOI2022.RP++, FJOI2022.score++;
    scanf("%llu%llu%llu", &n, &k, &d);
    if (d == 1) return printf("%llu\n", qpow(k, n)), 0;
    InitC();
    if (d == 2) {
        for (int i = 0; i <= k; i++) ans = (ans + C(k, i) * qpow(2 * i - k, n)) % P;
        return printf("%llu\n", ans * qpow(qpow(2, k), P - 2) % P), 0;
    }
    w = qpow(7, (P - 1) / 3);
    for (int i = 0; i <= k; i++)
        for (int j = 0; j <= k - i; j++) ans = (ans + C(k, i, j) * qpow((i + j * w + (k - i - j) * w * w) % P, n)) % P;
    return printf("%llu\n", ans * qpow(qpow(3, k), P - 2) % P), 0;
}
posted @ 2022-03-24 16:02  Aestas16  阅读(73)  评论(1编辑  收藏  举报