题解:P4721 【模板】分治 FFT
Union_Find · · 题解
多项式求逆
化简原始式子
直接多项式求逆即可。
int n;
poly f, g;
signed main(){
n = rd() - 1, g = get(n);
g[0] = 1;
for (int i = 1; i <= n; i++) g[i] = (P - rd()) % P;
f = inv(g, n);
for (int i = 0; i <= n; i++) printf ("%d ", f[i]);
return 0;
}
分治 NTT
好吧,言归正传,这题是分治 NTT 板子,我们考虑用分治做,用类似于 cdq 分治优化 dp 的思路来做。
首先假设分治区间为
- 分治处理
[l,mid] 的f 值。 - 处理
[l,mid] 对[mid+1,r] 的f 的影响。 - 分治
[mid+1,r] 。
关键是第
可以直接 NTT 做到
void solve(int l, int r){
if (l == r) return ;
int mid = (l + r) >> 1;
solve(l, mid), h = get(n);
for (int i = l; i <= mid; i++) h[i] = f[i];
h = mod(h * g, n + 1);
for (int i = mid + 1; i <= r; i++) f[i] = (f[i] + h[i]) % P;
solve(mid + 1, r);
}
然后就 T 了。毕竟常数太大了,我们来优化一下。
优化很简单,我们发现前面为
void solve(int l, int r){
if (l == r) return ;
int mid = (l + r) >> 1;
solve(l, mid), h = get(mid - l), t= get(r - l);
for (int i = l; i <= mid; i++) h[i - l] = f[i];
for (int i = 1; i <= r - l; i++) t[i] = g[i];
h = h * t;
for (int i = mid + 1; i <= r; i++) f[i] = (f[i] + h[i - l]) % P;
solve(mid + 1, r);
}
signed main(){
n = rd() - 1, f = g = get(n);
for (int i = 1; i <= n; i++) g[i] = rd();
f[0] = 1, solve(0, n);
for (int i = 0; i <= n; i++) printf ("%d ", f[i]);
return 0;
}