分治FFT
考虑计算这么一个式子f(i)=∑j=1ifi−jg(j)f(i) = \sum\limits_{j = 1} ^{i} f_{i - j}g(j)f(i)=j=1∑ifi−jg(j),给定g(x)g(x)g(x),求f(x)f(x)f(x),边界条件f(0)=1f(0) = 1f(0)=1。
假设我们已经算出[l,mid][l, mid][l,mid],考虑计算其对[mid+1,r][mid + 1, r][mid+1,r]的贡献w(i)w(i)w(i),
有w(x)=∑i=lmidf(i)g(x−i)w(x) = \sum\limits_{i = l} ^{mid} f(i) g(x - i)w(x)=i=l∑midf(i)g(x−i),因为[mid+1,r][mid + 1, r][mid+1,r]区间还没开始计算,所以f(i)=0,i∈[mid,x−1]f(i) = 0, i \in [mid, x - 1]f(i)=0,i∈[mid,x−1],则w(x)=∑i=lx−1f(i)g(x−i)w(x) = \sum\limits_{i = l} ^{x - 1} f(i) g(x - i)w(x)=i=l∑x−1f(i)g(x−i)
我们设a(i)=f(i+l),b(i)=g(i+1)a(i) = f(i + l), b(i) = g(i + 1)a(i)=f(i+l),b(i)=g(i+1),上式w(x)=∑i=0x−l−1a(i)b(x−l−i+1)w(x) = \sum\limits_{i = 0} ^{x - l - 1} a(i)b(x - l - i + 1)w(x)=i=0∑x−l−1a(i)b(x−l−i+1)
有w(x)=c(x−l+1)=∑i=0x−l−1a(i)b(x−l−i+1)w(x) = c(x - l + 1) = \sum\limits_{i = 0} ^{x - l - 1}a(i) b(x - l - i + 1)w(x)=c(x−l+1)=i=0∑x−l−1a(i)b(x−l−i+1)
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 5e6 + 10, mod = 998244353, inv2 = mod + 1 >> 1;int a[N], b[N], c[N], d[N], r[N];int quick_pow(int a, int n) {int ans = 1;while (n) {if (n & 1) {ans = 1ll * ans * a % mod;}a = 1ll * a * a % mod;n >>= 1;}return ans;
}void get_r(int lim) {for (int i = 0; i < lim; i++) {r[i] = (i & 1) * (lim >> 1) + (r[i >> 1] >> 1);}
}void NTT(int *f, int lim, int rev) {for (int i = 0; i < lim; i++) {if (i < r[i]) {swap(f[i], f[r[i]]);}}for (int mid = 1; mid < lim; mid <<= 1) {int wn = quick_pow(3, (mod - 1) / (mid << 1));for (int len = mid << 1, cur = 0; cur < lim; cur += len) {int w = 1;for (int k = 0; k < mid; k++, w = 1ll * w * wn % mod) {int x = f[cur + k], y = 1ll * w * f[cur + mid + k] % mod;f[cur + k] = (x + y) % mod, f[cur + mid + k] = (x - y + mod) % mod;}}}if (rev == -1) {int inv = quick_pow(lim, mod - 2);reverse(f + 1, f + lim);for (int i = 0; i < lim; i++) {f[i] = 1ll * f[i] * inv % mod;}}
}void DACFFT(int l, int r) {if (l == r) {return ;}int mid = l + r >> 1;DACFFT(l, mid);for (int i = 0; i <= mid - l; i++) {c[i] = b[i + l];}for (int i = 0; i < r - l; i++) {d[i] = a[i + 1];}int lim = 1;while (lim <= r - l + mid - l + 1) {lim <<= 1;}get_r(lim);NTT(c, lim, 1);NTT(d, lim, 1);for (int i = 0; i < lim; i++) {c[i] = 1ll * c[i] * d[i] % mod;}NTT(c, lim, -1);for (int i = mid - l; i <= r - l - 1; i++) {b[i + l + 1] = (b[i + l + 1] + c[i]) % mod;}for (int i = 0; i < lim; i++) {c[i] = d[i] = 0;}DACFFT(mid + 1, r);
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int n;scanf("%d", &n);for (int i = 1; i < n; i++) {scanf("%d", &a[i]);}b[0] = 1;DACFFT(0, n - 1);for (int i = 0; i < n; i++) {printf("%d%c", b[i], i == n ? '\n' : ' ');}return 0;
}