HDU 6061 - RXD and functions | 2017 Multi-University Training Contest 3
每次NTT都忘记初始化,真的是写一个小时,Debug两个小时- -
/* HDU 6061 - RXD and functions [ NTT ] | 2017 Multi-University Training Contest 3 题意: 给定多项式 F(x) = ∑[0<=i<=n] f(i)*x^i 求多项式 G(x) = F(x-a) n <= 1e5 分析: 设 G(x) = ∑ g(i)*x^i 将 F(x-a) 按二项式定理展开后易得: g(x) = ∑[x<=y<=n] Comb(y,x) * f(y) * (-a)^(y-x) 打开组合数,移项: g(x)*x! = ∑[x<=y<=n] f(y)*y! * (-a)^(y-x) / (y-x)! 设 g'(x) = g(x)*x! p(x) = f(y)*y! q(x) = (-a)^x/x! 则 g'(x) = ∑[x<=y<=n] p(y) * q(y-x) = ∑[1<=y<=n-x] p(y+x) * q(y) 设 g''(x) = g'(n-x) 则 g''(x) = ∑[1<=y<=x] p(n-(x-y)) * q(y) 设 p'(x) = p(n-x) 则 g''(x) = ∑[1<=y<=x] p'(x-y) * q(y) 算出这个卷积后回带即可 */ #include <bits/stdc++.h> using namespace std; #define LL long long const int N = 1e5+5; const LL MOD = 998244353; namespace NTT { const int G = 3; const int NUM = 20; LL wn[20]; LL mul(LL x, LL y) { return x*y% MOD; } LL PowMod(LL a, LL b) { LL res = 1; a %= MOD; while (b) { if (b&1) res = mul(res, a); a = mul(a, a); b >>= 1; } return res; } void Init() { for (int i = 0; i < NUM; i++) { int t = 1<<i; wn[i] = PowMod(G, (MOD-1)/t); } } void Change(LL a[], int len) { int i, j, k; for (i = 1, j = len/2; i < len-1; i++) { if (i < j) swap(a[i], a[j]); k = len/2; while (j >= k) { j -= k; k /= 2; } if (j < k) j += k; } } void NTT(LL a[], int len, int on) { Change(a, len); int id = 0; for (int h = 2; h <= len; h <<= 1) { id++; for (int j = 0; j < len; j += h) { LL w = 1; for (int k = j; k < j + h/2; k++) { LL u = a[k] % MOD; LL t = mul(a[k+h/2], w); a[k] = (u+t) % MOD; a[k+h/2] = ((u-t)% MOD + MOD ) % MOD; w = mul(w, wn[id]); } } } if (on == -1) { for (int i = 1; i < len/2; i++) swap(a[i], a[len-i]); LL inv = PowMod(len, MOD-2); for (int i = 0; i < len; i++) a[i] = mul(a[i], inv); } } void solve(LL a[], int n, LL b[], int m) { int len = 1; while (len < n*2 || len < m*2) len <<= 1; for (int i = n; i < len; i++) a[i] = 0; for (int i = m; i < len; i++) b[i] = 0; NTT(a, len, 1); NTT(b, len, 1); for (int i = 0; i < len; i++) a[i] = mul(a[i], b[i]); NTT(a, len, -1); } } LL f[N], p[N<<3], q[N<<3]; LL a; int n, m; LL F[N], Finv[N], inv[N]; void init(){ inv[1] = 1; for (int i = 2; i < N; i++) { inv[i] = (MOD-MOD/i) * inv[MOD%i] % MOD; } F[0] = Finv[0] = 1; for (int i = 1; i < N; i++){ F[i] = F[i-1] * i % MOD; Finv[i] = Finv[i-1] * inv[i] % MOD; } } void solve() { for (int i = 0; i <= n; i++) p[i] = F[i] * f[i] % MOD;//p(x) q[0] = 1; for (int i = 1; i <= n; i++) q[i] = q[i-1] * (MOD-a) % MOD * inv[i] % MOD;//q(x) for (int i = 0; i <= n/2; i++) swap(p[i], p[n-i]);//p'(x) NTT::solve(p, n+1, q, n+1);//g''(x) for (int i = 0; i <= n/2; i++) swap(p[i], p[n-i]);//g'(x) for (int i = 0; i <= n; i++) p[i] = p[i] * Finv[i] % MOD;//g(x) } int main() { init(); NTT::Init(); while (~scanf("%d", &n)) { for (int i = 0; i <= n; i++) scanf("%lld", &f[i]); scanf("%d", &m); a = 0; for (int i = 1; i <= m; i++) { LL x; scanf("%lld", &x); a = (a+x) % MOD; } solve(); for (int i = 0; i <= n; i++) printf("%lld ", p[i]); puts(""); } }
我自倾杯,君且随意