RXD and functions
首先是有一个结论,对多项式做任意多次 transformation ,其结果跟做一次 transformation
T
r
(
f
,
∑
i
=
1
m
a
i
)
Tr(f, \sum\limits_{i = 1} ^{m} a_i)
Tr(f,i=1∑mai)的结果是一样的,所以我们约定
a
=
−
∑
i
=
1
m
a
i
a = -\sum\limits_{i = 1} ^{m} a_i
a=−i=1∑mai。
g
=
f
(
x
+
a
)
∑
i
=
0
n
c
i
(
x
+
a
)
i
∑
i
=
0
n
∑
j
=
0
i
c
i
i
!
j
!
(
i
−
j
)
!
x
j
a
i
−
j
我
们
考
虑
只
求
这
个
多
项
式
的
x
j
系
数
g
j
=
∑
i
=
j
n
c
i
i
!
j
!
(
i
−
j
)
!
a
i
−
j
g
j
=
∑
i
=
0
n
−
j
c
i
+
j
(
i
+
j
)
!
j
!
i
!
a
i
g
j
=
1
j
!
∑
i
=
0
n
−
j
(
c
i
+
j
(
i
+
j
)
!
)
×
(
a
i
i
!
)
设
f
(
n
)
=
c
n
n
!
,
h
(
n
)
=
a
n
n
!
不
难
发
现
后
项
像
是
多
项
式
卷
积
的
形
式
,
考
虑
翻
转
a
i
i
,
即
i
=
n
−
i
g
j
=
1
j
!
∑
i
=
0
n
−
j
f
(
i
+
j
)
h
(
n
−
i
)
这
就
是
一
个
完
美
的
卷
积
形
式
了
,
于
是
可
以
N
T
T
求
解
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;
}