Solution 【模板】分治 FFT
题目大意:给定(g_{1ldots n-1},f_0=1),求(f_{1 ldots n-1}),其中(f_i=sum_{j=1}^{i}f_{i-j}g_j),对(998244353)取模
NTT、分治
分析:
有两种做法:首先可以多项式求逆(现在还不会)
然后可以用分治加上NTT(FFT)优化卷积的方法
首先我们注意到,对于一个位置(i),它依赖于([0,i-1])处(f)的值,如果依次计算的话时间复杂度无法承受
这个时候可以用分治,计算一段区间内的(f)值对于另一段区间的贡献
类似于(cdq)分治,我们计算完左区间后,考虑左区间会对右区间产生多少贡献。这个直接将左区间的(f)和(g)做一个卷积就可以了
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 3e5 + 100,mod = 998244353;
// g = 3,inv = 332748118
namespace Fast_IO{
const int bufsiz = 1 << 20;
char buf[bufsiz],*ed = buf + bufsiz,*p = buf;
inline char getch(){
#ifndef ONLINE_JUDGE
return getchar();
#endif
if(p == ed){
fread(buf,sizeof(char),bufsiz,stdin);
p = buf;
}
return *(p++);
}
inline int read(){
int x = 0;char c = getch();
while(!isdigit(c))c = getch();
while(isdigit(c))x = x * 10 + c - '0',c = getch();
return x;
}
}using Fast_IO::read;
inline int add(int a,int b){return (a + b) % mod;}
inline int sub(int a,int b){return ((a - b) % mod + mod) % mod;}
inline int mul(int a,int b){return (1ll * a * b) % mod;}
inline int qpow(int a,int b){
int res = 1,base = a;
while(b){
if(b & 1)res = mul(res,base);
base = mul(base,base);
b >>= 1;
}
return res;
}
inline int inv(int x){return qpow(x,mod - 2);}
int n,N,tr[maxn << 1],g[maxn << 1],f[maxn << 1],tmp1[maxn << 1],tmp2[maxn << 1];
inline void ntt(int f[],int N,int flag){
for(int i = 0;i < N;i++)
if(i < tr[i])swap(f[i],f[tr[i]]);
for(int p = 2;p <= N;p <<= 1){
int len = p >> 1,unit = qpow(flag == 1 ? 3 : 332748118,(mod - 1) / p);
for(int k = 0;k < N;k += p){
int g = 1;
for(int l = k;l < k + len;l++){
int tt = mul(f[l + len],g);
f[l + len] = sub(f[l],tt);
f[l] = add(f[l],tt);
g = mul(g,unit);
}
}
}
}
inline void cdq(int a,int b){
if(a == b)return;
int mid = (a + b) >> 1;
cdq(a,mid);
int N = (b - a + 1) << 1;
for(int i = 0;i < N;i++)
tr[i] = (tr[i >> 1] >> 1) | ((i & 1) ? (N >> 1) : 0);
for(int i = a;i <= mid;i++)tmp1[i - a] = f[i];
ntt(tmp1,N,1);
for(int i = 1;i <= b - a;i++)tmp2[i] = g[i];
ntt(tmp2,N,1);
for(int i = 0;i < N;i++)tmp1[i] = mul(tmp1[i],tmp2[i]);
ntt(tmp1,N,-1);
const int iv = inv(N);
for(int i = mid + 1;i <= b;i++)
f[i] = add(f[i],mul(tmp1[i - a],iv));
for(int i = 0;i < N;i++)tmp1[i] = tmp2[i] = 0;
cdq(mid + 1,b);
}
int main(){
n = read();
for(int i = 1;i < n;i++)g[i] = read();
for(N = 1;N < n;N <<= 1);
f[0] = 1;
cdq(0,N - 1);
for(int i = 0;i < n;i++)printf("%d ",f[i]);
return 0;
}