1 条题解
-
0

#include <bits/stdc++.h> #define lg2 std::__lg typedef long long ll; const int N = 530000, mod = 998244353, half_mod = (mod + 1) / 2, root = 31; typedef int vec[N], *pvec; vec fact, inv, finv; inline int & reduce(int &x) {return x += x >> 31 & mod;} inline int & neg(int &x) {return x = (!x - 1) & (mod - x);} inline void fma(int &x, const int y, const int z) {x = (x + (ll)y * z) % mod;} ll PowerMod(ll a, int n, ll c = 1) {for (; n; n >>= 1, a = a * a % mod) if (n & 1) c = c * a % mod; return c;} void init() { int i; for (inv[1] = 1, i = 2; i < N; ++i) inv[i] = (ll)(mod - mod / i) * inv[mod % i] % mod; for (*finv = *fact = i = 1; i < N; ++i) fact[i] = (ll)fact[i - 1] * i % mod, finv[i] = (ll)finv[i - 1] * inv[i] % mod; } namespace Poly { int l, n; vec rev, x, y; void NTT_init(int len) { if (l == len) return; n = 1 << (l = len); ll g = PowerMod(root, 1 << (23 - l)); *x = 1, *rev = 0; for (int i = 1; i < n; ++i) x[i] = x[i - 1] * g % mod, rev[i] = rev[i >> 1] >> 1 | (i & 1) << (l - 1); } void DNTT(int *d, int *t) { int i, *j, *k, len = 1, delta = n, R; for (i = 0; i < n; ++i) t[rev[i]] = d[i]; for (i = 0; i < l; ++i) { delta >>= 1; for (k = x, j = y; j < y + len; k += delta, ++j) *j = *k; for (j = t; j < t + n; j += len << 1) for (k = j; k < j + len; ++k) R = (ll)y[k - j] * k[len] % mod, k[len] = (*k - R < 0 ? *k - R + mod : *k - R), *k = (*k + R >= mod ? *k + R - mod : *k + R); len <<= 1; } } inline void IDNTT(int *d, int *t) { ll iv = mod - (mod - 1) / n; DNTT(d, t), std::reverse(t + 1, t + n); for (int i = 0; i < n; ++i) t[i] = t[i] * iv % mod; } vec B1, B2, B3, B4, B5, B6, B7; void Mul(int deg, pvec a, pvec b, pvec c) { if (!deg) {*c = (ll)*a * *b % mod; return;} NTT_init(lg2(deg) + 1); DNTT(a, c), DNTT(b, B1); for (int i = 0; i < n; ++i) B1[i] = (ll)B1[i] * c[i] % mod; IDNTT(B1, c); } void Inv(int deg, pvec a, pvec b) { int len, i; ll iv = half_mod; *b = PowerMod(*a, mod - 2), b[1] = 0, *B1 = *a, B1[1] = a[1]; for (len = 0; 1 << len < deg; ++len) { NTT_init(len + 2); memset(b + (n >> 1), 0, n << 1), DNTT(b, B2); memset(B1 + (n >> 1), 0, n << 1), DNTT(B1, B3); for (i = 0; i < n; ++i) reduce(B2[i] = B2[i] * (2ll - (ll)B2[i] * B3[i] % mod) % mod); DNTT(B2, B3), std::reverse(B3 + 1, B3 + n), iv = (iv >> 1) + half_mod; for (i = 0; i < n >> 1; ++i) b[i] = B3[i] * iv % mod; memcpy(B1 + i, a + i, n << 1); } } void Diff(int deg, pvec a, pvec b) {for (int i = 1; i <= deg; ++i) b[i - 1] = (ll)a[i] * i % mod;} void Intg(int deg, pvec a, pvec b, int ct = 0) {for (int i = 1; i <= deg; ++i) b[i] = (ll)a[i - 1] * inv[i] % mod; *b = ct;} void Ln(int deg, pvec a, pvec b) { if (!--deg) {*b = 0; return;} int i, j = deg * 2 - 1; NTT_init(lg2(j) + 1); Diff(deg, a, B4), Inv(deg, a, B5); for (i = deg; i < n; ++i) B4[i] = B5[i] = 0; Mul(j, B4, B5, B6), Intg(deg, B6, b); } void Exp(int deg, pvec a, pvec b) { int len, i, n = 2; *b = 1, b[1] = 0; for (len = 0; 1 << len < deg; ++len, n <<= 1) { Ln(n, b, B7), *B7 = 1; for (i = 1; i < n; ++i) reduce(B7[i] = a[i] - B7[i]); memset(B7 + n, 0, n << 2), memset(b + n, 0, n << 2); Mul((n << 1) - 1, b, B7, B6), memcpy(b, B6, n << 2); } } } int D; vec f, g, df, dg, exp_dg; vec I, C0, C1; /* df = sum_i f(x^i) / i g = e^df - 1 dg = x sum_i g(x^i) / i e^dg (1 - e^df f) x e^dg x - f => f = ------------------- = f + --------------- 1 - e^df e^dg x 1 - e^df e^dg x */ int main() { int i, j, lim, len, n = 8; init(), std::fill(I, I + N, 1); scanf("%d", &D); f[1] = f[2] = 1, f[3] = 3, df[1] = dg[1] = 1; for (len = 2; 1 << len <= D; ++len, n <<= 1) { for (i = 2; i < n; ++i) for (lim = (n - 1) / i, j = I[i]; j <= lim; ++j) fma(df[j * i], f[j], inv[i]); for (i = n >> 2; i < n >> 1; ++i) reduce(df[i] += f[i] - mod); Poly::NTT_init(len + 2); Poly::Exp(n, df, g); for (i = 2; i < n; ++i) for (lim = (n - 1) / i; I[i] <= lim; ++I[i]) fma(dg[I[i] * i], g[I[i]], inv[i]); for (i = n >> 2; i < n; ++i) reduce(dg[i] += g[i] - mod); Poly::Exp(n, dg, exp_dg); for (i = n >> 1; i < n; ++i) reduce(dg[i] -= g[i]); Poly::Mul(n * 2 - 1, g, exp_dg, C0 + 1), *C0 = 1; for (i = 1; i < n; ++i) neg(C0[i]); memset(C0 + n, 0, (n + 1) << 2); Poly::Inv(n >> 1, C0, C1); Poly::Mul(n - 1, C1, exp_dg + (n >> 1) - 1, f + (n >> 1)); } for (i = 1; i <= D; ++i) printf("%d\n", f[i]); return 0; }
- 1
信息
- ID
- 4681
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者