RXD and functions
首先是有一个结论,对多项式做任意多次 transformation ,其结果跟做一次 transformation Tr(f,∑i=1mai)Tr(f, \sum\limits_{i = 1} ^{m} a_i)Tr(f,i=1∑mai)的结果是一样的,所以我们约定a=−∑i=1maia = -\sum\limits_{i = 1} ^{m} a_ia=−i=1∑mai。
g=f(x+a)∑i=0nci(x+a)i∑i=0n∑j=0icii!j!(i−j)!xjai−j我们考虑只求这个多项式的xj系数gj=∑i=jncii!j!(i−j)!ai−jgj=∑i=0n−jci+j(i+j)!j!i!aigj=1j!∑i=0n−j(ci+j(i+j)!)×(aii!)设f(n)=cnn!,h(n)=ann!不难发现后项像是多项式卷积的形式,考虑翻转aii,即i=n−igj=1j!∑i=0n−jf(i+j)h(n−i)这就是一个完美的卷积形式了,于是可以NTT求解g = f(x + a)\\ \sum_{i = 0} ^{n} c_i(x + a) ^ i\\ \sum_{i = 0} ^{n} \sum_{j = 0} ^{i}c_i \frac{i!}{j!(i - j)!} x ^ j a ^ {i - j}\\ 我们考虑只求这个多项式的x ^ j系数\\ g_j = \sum_{i = j} ^{n} c_i \frac{i!}{j!(i - j)!}a ^{i - j}\\ g_j = \sum_{i = 0} ^{n - j} c_{i + j} \frac{(i + j)!}{j! i!} a ^ i\\ g_j = \frac{1}{j!} \sum_{i = 0} ^{n - j} (c_{i + j} (i + j)!) \times (\frac{a ^i}{i!})\\ 设f(n) = c_{n} n!, h(n) = \frac{a ^ n}{n!} \\ 不难发现后项像是多项式卷积的形式,考虑翻转\frac{a ^ i}{ i},即i = n - i\\ g_j = \frac{1}{j!} \sum_{i = 0} ^{n - j} f(i + j) h(n - i)\\ 这就是一个完美的卷积形式了,于是可以NTT求解 g=f(x+a)i=0∑nci(x+a)ii=0∑nj=0∑icij!(i−j)!i!xjai−j我们考虑只求这个多项式的xj系数gj=i=j∑ncij!(i−j)!i!ai−jgj=i=0∑n−jci+jj!i!(i+j)!aigj=j!1i=0∑n−j(ci+j(i+j)!)×(i!ai)设f(n)=cnn!,h(n)=n!an不难发现后项像是多项式卷积的形式,考虑翻转iai,即i=n−igj=j!1i=0∑n−jf(i+j)h(n−i)这就是一个完美的卷积形式了,于是可以NTT求解
#include <bits/stdc++.h>using namespace std;const int N = 1e6 + 10, mod = 998244353;int r[N];int quick_pow(int a, int n) {int ans = 1;while (n) {if (n & 1) {ans = 1ll * a * ans % 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;}}
}int a[N], c[N], A[N], B[N], fac[N], ifac[N], n, m, sum;void init() {fac[0] = 1;for (int i = 1; i < N; i++) {fac[i] = 1ll * fac[i - 1] * i % mod;}ifac[N - 1] = quick_pow(fac[N - 1], mod - 2);for (int i = N - 2; i >= 0; i--) {ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;}
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);init();while (scanf("%d", &n) != EOF) {for (int i = 0; i <= n; i++) {scanf("%d", &c[i]);}scanf("%d", &m);sum = 0;for (int i = 1; i <= m; i++) {scanf("%d", &a[i]);sum = (sum + a[i]) % mod;}sum = (mod - sum) % mod;int cur = 1;for (int i = 0; i <= n; i++) {A[i] = 1ll * c[i] * fac[i] % mod;B[n - i] = 1ll * ifac[i] * cur % mod;cur = 1ll * cur * sum % mod;}int lim = 1;while (lim <= 2 * n) {lim <<= 1;}get_r(lim);NTT(A, lim, 1);NTT(B, lim, 1);for (int i = 0; i < lim; i++) {A[i] = 1ll * A[i] * B[i] % mod;}NTT(A, lim, -1);for (int i = 0; i <= n; i++) {printf("%lld ", 1ll * ifac[i] * A[n + i] % mod);}puts("");for (int i = 0; i < lim; i++) {A[i] = B[i] = 0;}}return 0;
}