loj 6268 分拆数

令 $f_n$ 为将 $n$ 进行分拆的方案数

例如,$4=1+1+1+1=1+1+2=1+3=2+2$,则 $f(4) = 5$

求 $f(1) \sim f(n)$ 膜 $998244353$

$n \leq 100000$

sol:

因为 $1+x+x^2+x^3+...= \frac{1}{1-x}$

则答案的生成函数为 $\prod \frac{1}{1-x^i}$

这个东西可以考虑他的 $ln$

$ln(\frac{1}{1-x^i}) = \sum \frac{x^{i \times j}}{j}$

则 $ln(\prod \frac{1}{1-x^i}) = \sum \sum \frac{x^{i \times j}}{j}$(乘法就是指数上的加法)

$\sum \sum \frac{x^{i \times j}}{j}$ 可以直接枚举 $i$ 和 $i$ 的倍数来求,是 $O(nlogn)$ 的

然后直接多项式 exp

五边形数是啥,不会

#include <bits/stdc++.h>
#define LL long long
#define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
#define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
using namespace std;
inline int read() {
    int x = 0, f = 1;
    char ch;
    for (ch = getchar(); !isdigit(ch); ch = getchar())
        if (ch == '-')
            f = -f;
    for (; isdigit(ch); ch = getchar()) x = 10 * x + ch - '0';
    return x * f;
}
const int maxn = 600010, mod = 998244353;
int F[maxn], G[maxn];
inline int skr(int x, int t) {
    int res = 1;
    for (; t; x = 1LL * x * x % mod, t >>= 1)
        if (t & 1)
            res = 1LL * res * x % mod;
    return res;
}
int r[maxn], lg[maxn], temp[maxn];
int inv[maxn], ifac[maxn], fac[maxn];
inline int skr(int x, LL t) {
    int res = 1;
    while (t) {
        if (t & 1)
            res = 1LL * res * x % mod;
        x = 1LL * x * x % mod;
        t = t >> 1;
    }
    return res;
}
inline void fft(int *a, int n, int type) {
    for (int i = 0; i < n; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lg[n] - 1));
    for (int i = 0; i < n; i++)
        if (i < r[i])
            swap(a[i], a[r[i]]);
    for (int i = 1; i < n; i <<= 1) {
        int wn = skr(3, (mod - 1) / (i << 1));
        if (type == -1)
            wn = skr(wn, mod - 2);
        // cout << wn << endl;
        for (int j = 0; j < n; j += (i << 1)) {
            int w = 1;
            for (int k = 0; k < i; k++, w = (1LL * (LL)w * (LL)wn) % mod) {
                int x = a[j + k], y = (1LL * (LL)w * (LL)a[j + k + i]) % mod;
                a[j + k] = (x + y) % mod;
                a[j + k + i] = (((x - y) % mod) + mod) % mod;
            }
        }
    }
    if (type == -1) {
        int inv = skr(n, mod - 2);
        for (int i = 0; i < n; i++) a[i] = ((LL)a[i] * (LL)inv) % mod;
    }
}
inline void Inverse(int *a, int *b, int n) {
    if (n == 1) {
        b[0] = skr(a[0], mod - 2);
        return;
    }
    Inverse(a, b, n >> 1);
    memcpy(temp, a, n * sizeof(int));
    memset(temp + n, 0, n * sizeof(int));
    fft(temp, n << 1, 1);
    fft(b, n << 1, 1);
    for (int i = 0; i < (n << 1); i++)
        b[i] = 1LL * b[i] * ((2LL - 1LL * temp[i] * b[i] % mod + mod) % mod) % mod;
    fft(b, n << 1, -1);
    memset(b + n, 0, n * sizeof(int));
}
int c[maxn], d[maxn];
inline void Ln(int *a, int *b, int n) {
    Inverse(a, c, n);
    for (int i = 0; i < n - 1; ++i) d[i] = (LL)(i + 1) * a[i + 1] % mod;
    d[n - 1] = 0;
    fft(c, n << 1, 1);
    fft(d, n << 1, 1);
    for (int i = 0; i < (n << 1); ++i) c[i] = 1LL * d[i] * c[i] % mod;
    fft(c, (n << 1), -1);
    for (int i = 1; i < (n << 1); ++i) b[i] = 1LL * inv[i] * c[i - 1] % mod;
    b[0] = 0;
    for (int i = 0; i < (n << 1); ++i) c[i] = d[i] = 0;
}
int temp_w[maxn], temp_Ln[maxn];
inline void Exp(int *a, int *b, int n) {
    if (n == 1) {
        b[0] = 1;
        return;
    }
    Exp(a, b, n >> 1);
    memcpy(temp_w, b, sizeof(int) * n);
    memset(temp_w + n, 0, sizeof(int) * n);
    Ln(b, temp_Ln, n);
    for (int i = 0; i < n; i++) temp_Ln[i] = (mod + a[i] - temp_Ln[i]) % mod;
    (temp_Ln[0] += 1) %= mod;
    fft(temp_w, n << 1, 1);
    fft(temp_Ln, n << 1, 1);
    for (int i = 0; i < (n << 1); i++) temp_w[i] = 1LL * temp_w[i] * temp_Ln[i] % mod;
    fft(temp_w, n << 1, -1);
    memcpy(b, temp_w, n * sizeof(int));
    memset(b + n, 0, n * sizeof(int));
    memset(temp_w, 0, sizeof(int) * (n << 1));
    memset(temp_Ln, 0, sizeof(int) * (n << 1));
}
int main() {
    int n = read(); lg[0] = -1;
    rep(i, 1, 600000) lg[i] = lg[i >> 1] + 1;
    int len = 1; for(; len <= n; len <<= 1);
    inv[1] = ifac[0] = fac[0] = 1;
    rep(i, 1, len) {
        if (i != 1) inv[i] = -(LL)mod / i * inv[mod % i] % mod;
        inv[i] = ((inv[i] % mod) + mod) % mod;
        ifac[i] = (LL)ifac[i - 1] * inv[i] % mod;
        fac[i] = (LL)fac[i - 1] * i % mod;
    }
    rep(i, 1, n) rep(j, 1, n / i) F[i * j] = (F[i * j] + inv[j]) % mod;
    //rep(i, 1, n) cout << F[i] << " ";
    //cout << endl;
    Exp(F, G, len); rep(i, 1, n) cout << G[i] << '\n';
}
View Code

 

posted @ 2019-04-16 11:41  探险家Mr.H  阅读(437)  评论(0编辑  收藏  举报