分治FFT/NTT

考虑对当前左区间对右区间的贡献,由于右区间的F未更新,可以更改指标

\begin{array}{rcl}
F_x&=&\sum\limits_{i=L}^{mid}F_iG_{x-i}
\\ &=&\sum\limits_{i=L}^{x}F_iG_{x-i}
\\ &=&\sum\limits_{i=0}^{x-L}F_{L+i}G_{x-L-i}
\end{array}

设$A_i=F_{i+L},B_i=G_i$

\begin{array}{rcl}
F_x=C_{x-L}=\sum\limits_{i=0}^{x-L}A_iB{x-L-i}
\end{array}

模板:

分治FFT/NTT
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #define ll long long
 6 #define reg register
 7 #define F(i,a,b) for(register int (i)=(a);(i)<=(b);++(i))
 8 using namespace std;
 9 int read();
10 const int N=400005;
11 const ll mod=998244353ll;
12 int n,h,cs;
13 int rev[N];
14 ll ih;
15 ll f[N],g[N],a[N],b[N],omg[N],inv[N];
16 ll qpow(ll x,ll b,ll mod=998244353ll,ll ans=1ll)
17 {
18     for(;b;b>>=1,x=x*x%mod)
19         if(b&1)ans=ans*x%mod;
20     return ans;
21 }
22 ll mo(ll x){return x>=mod?x-mod:x;}
23 void init(int len)
24 {
25     h=1,cs=0;while(h<=len)h<<=1,++cs;
26     ih=qpow(h,mod-2);
27     omg[0]=inv[0]=1ll;omg[1]=qpow(3,(mod-1)/h);inv[1]=qpow(omg[1],mod-2);
28     for(reg int i=0;i<h;++i){
29         a[i]=b[i]=0;
30         rev[i]=(rev[i>>1]>>1)|((i&1)<<cs-1);
31         if(i>1)omg[i]=omg[i-1]*omg[1]%mod,inv[i]=inv[i-1]*inv[1]%mod;
32     }
33 }
34 void NTT(ll *a,ll *omg,int op)
35 {
36     for(reg int i=0;i<h;++i)if(i<rev[i])swap(a[i],a[rev[i]]);
37     for(reg int l=2,mid=1;l<=h;l<<=1,mid<<=1){
38         for(ll *p=a;p!=a+h;p+=l)
39             for(reg int i=0;i<mid;++i){
40                 ll t=omg[h/l*i]*p[i+mid]%mod;
41                 p[i+mid]=mo(p[i]-t+mod);
42                 p[i]=mo(p[i]+t);
43             }
44     }
45     if(op==-1)for(reg int i=0;i<h;++i)a[i]=a[i]*ih%mod;
46 }
47 void solve(int l,int r)
48 {
49     if(l==r)return;
50     int mid=l+r>>1;
51     solve(l,mid);
52     int len=r-l+1;
53     init(len);
54     F(i,l,mid)a[i-l]=f[i];
55     for(reg int i=0;i<len;++i)b[i]=g[i];
56     NTT(a,omg,1);NTT(b,omg,1);
57     for(reg int i=0;i<h;++i)a[i]=a[i]*b[i]%mod;
58     NTT(a,inv,-1);
59     F(i,mid+1,r)f[i]=mo(f[i]+a[i-l]);
60     solve(mid+1,r);
61 }
62 int main()
63 {
64     n=read();
65     F(i,1,n-1)g[i]=read();
66     f[0]=1ll;
67     solve(0,n-1);
68     F(i,0,n-1)printf("%lld ",f[i]);puts("");
69     return 0;
70 }
71 int read()
72 {
73     int x=0,fh=1;char tc=getchar();
74     while(tc<'0'||tc>'9'){if(tc=='-')fh=-1;tc=getchar();}
75     while(tc>='0'&&tc<='9')x=(x<<3)+(x<<1)+(tc^48),tc=getchar();
76     return fh*x;
77 }
View Code
上一篇:一步一步构使用Jenkins配置Jenkins项目


下一篇:组件化开发方法