模板分治FFT
Posted greenty1208
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板分治FFT相关的知识,希望对你有一定的参考价值。
题意
分析
如果我们已经求得了 f[L],f[L+1] ... f[mid],他们均能对f[mid+1],f[mid+2]...,f[R]产生贡献
对于x ∈ [mid+1,r] f[x] += sum_{i=L}^{mid}(f[i]*g[x-i])
等式右边满足卷积模式
具体看代码
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int n; 5 ll gg[400005],f[400005],A[400005],B[400005]; 6 int g=3,mod=998244353; 7 ll qpow(ll a,ll b) { 8 ll res=1; 9 while(b) { 10 if(b&1) res = res * a % mod; 11 a = a*a %mod; 12 b >>= 1; 13 } 14 return res; 15 } 16 int rev(int x,int r) { 17 int ans=0; 18 for(int i=0;i<r;i++) if(x&(1<<i)) ans+=1<<(r-i-1); 19 return ans; 20 } 21 void ntt(int n,ll a[],int on) { 22 int r = 0; 23 while((1<<r)<n) r++; 24 for(int i=0;i<n;i++) { 25 int tmp = rev(i,r); 26 if(i < tmp) swap(a[i],a[tmp]); 27 } 28 for(int s=1;s<=r;s++) { 29 int m = 1<<s; 30 ll wn=qpow(g,(mod-1)/m); 31 for(int k=0;k<n;k+=m){ 32 ll w=1; 33 for(int j=0;j<(m>>1);j++) { 34 ll t = w * a[k+j+(m>>1)] % mod; 35 ll u=a[k+j]; 36 a[k+j] = (u+t)%mod; 37 a[k+j+(m>>1)] = (u-t)%mod;if(a[k+j+(m>>1)]<0)a[k+j+(m>>1)]+=mod; 38 w = w*wn%mod; 39 } 40 } 41 } 42 if(on==-1) { 43 for(int i=1;i<(n>>1);i++) swap(a[i],a[n-i]); 44 ll inv = qpow(n,mod-2); 45 for(int i=0;i<n;i++) a[i] = a[i] * inv % mod; 46 } 47 } 48 void solve(int l,int r) { 49 if(l == r) return; 50 int mid = (r+l)>>1; 51 solve(l,mid); 52 int siz = r-l+1; 53 int len = 1; 54 while(len < siz+siz) len <<=1; 55 for(int i=0;i<len;i++) A[i] = B[i] = 0; 56 for(int i=l;i<=mid;i++) A[i-l] = f[i]; 57 for(int i=1;i<=r-l;i++) B[i] = gg[i]; 58 ntt(len,A,1);ntt(len,B,1); 59 for(int i=0;i<len;i++) A[i]=A[i]*B[i]%mod; 60 ntt(len,A,-1); 61 for(int i=mid+1;i<=r;i++) f[i] = (f[i] + A[i-l])%mod; 62 solve(mid+1,r); 63 } 64 int main() { 65 ios::sync_with_stdio(false); 66 cin >> n; 67 for(int i=1;i<n;i++) { 68 cin >> gg[i]; 69 gg[i] %= mod; 70 } 71 f[0] = 1; 72 solve(0,n-1); 73 for(int i=0;i<n;i++) cout<<f[i]<<" "; 74 cout<<" "; 75 }
以上是关于模板分治FFT的主要内容,如果未能解决你的问题,请参考以下文章