FFT各种模板
Posted kanbokedeshiwoerzi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFT各种模板相关的知识,希望对你有一定的参考价值。
丑陋敬请谅解:
求两列数的卷积:
递归版:
#include <stdio.h> #include <algorithm> #include <math.h> using namespace std; const double pi=acos(-1); int p[5000010],q[5000010]; struct complex { double x,y; complex(double xx=0,double yy=0) { x=xx; y=yy; } }a[5000100],b[5000100]; complex operator +(complex a,complex b){return complex(a.x+b.x,a.y+b.y);} complex operator -(complex a,complex b){return complex(a.x-b.x,a.y-b.y);} complex operator *(complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);} void DFT(int limit,complex *a) { if(limit==1) return; int mid=limit>>1; complex a1[mid],a2[mid]; for(int i=0;i<=limit;i+=2) { a1[i>>1]=a[i]; a2[i>>1]=a[i+1]; } DFT(mid,a1); DFT(mid,a2); complex wn=complex(cos(2.0*pi/limit),sin(2.0*pi/limit)); complex w=complex(1,0); for(int i=0;i<mid;i++,w=w*wn) { a[i]=a1[i]+w*a2[i]; a[i+mid]=a1[i]-w*a2[i]; } } int pow(int x,int y) { if(y==0) return 1; int t=pow(x,y/2); if(y%2==0) return t*t; return t*t*x; } void IDFT(int limit,complex *a) { if(limit==1) return; int mid=limit>>1; complex a1[mid],a2[mid]; for(int i=0;i<=limit;i+=2) { a1[i>>1]=a[i]; a2[i>>1]=a[i+1]; } IDFT(mid,a1); IDFT(mid,a2); complex wn=complex(cos(2.0*pi/limit),-sin(2.0*pi/limit)); complex w=complex(1,0); for(int i=0;i<mid;i++,w=w*wn) { a[i]=a1[i]+w*a2[i]; a[i+mid]=a1[i]-w*a2[i]; } } int main() { int k; scanf("%d",&k); int n=pow(2,k); for(int i=0;i<=n-1;i++) scanf("%d",&p[i]); for(int i=0;i<=n-1;i++) scanf("%d",&q[i]); for(int i=0;i<=n-1;i++) a[i]=p[i]; for(int i=0;i<=n-1;i++) b[i]=q[i]; int limit=2*n; DFT(limit,a); DFT(limit,b); for(int i=0;i<=limit;i++) a[i]=a[i]*b[i]; IDFT(limit,a); for(int i=0;i<=n-2;i++) printf("%d\n",(int)(a[i].x/limit+0.5)); printf("%d",(int)(a[n-1].x/limit+0.5)); }
非递归版+蝶形算法优化:
#include<stdio.h> #include <algorithm> #include<math.h> using namespace std; const int MAXN=1e7+10; const double Pi=acos(-1.0); int p[MAXN],q[MAXN]; struct complex { double x,y; complex (double xx=0,double yy=0){x=xx,y=yy;} }a[MAXN],b[MAXN]; complex operator + (complex a,complex b){ return complex(a.x+b.x , a.y+b.y);} complex operator - (complex a,complex b){ return complex(a.x-b.x , a.y-b.y);} complex operator * (complex a,complex b){ return complex(a.x*b.x-a.y*b.y , a.x*b.y+a.y*b.x);} int N,M; int l,r[MAXN]; int limit=1; void DFT(complex *A) { for(int i=0;i<limit;i++) if(i<r[i]) swap(A[i],A[r[i]]); for(int mid=1;mid<limit;mid<<=1) { complex Wn( cos(Pi/mid) , sin(Pi/mid) ); for(int R=mid<<1,j=0;j<limit;j+=R) { complex w(1,0); for(int k=0;k<mid;k++,w=w*Wn) { complex x=A[j+k],y=w*A[j+mid+k]; A[j+k]=x+y; A[j+mid+k]=x-y; } } } } void IDFT(complex *A) { for(int i=0;i<limit;i++) if(i<r[i]) swap(A[i],A[r[i]]); for(int mid=1;mid<limit;mid<<=1) { complex Wn( cos(Pi/mid) , -1.0*sin(Pi/mid) ); for(int R=mid<<1,j=0;j<limit;j+=R) { complex w(1,0); for(int k=0;k<mid;k++,w=w*Wn) { complex x=A[j+k],y=w*A[j+mid+k]; A[j+k]=x+y; A[j+mid+k]=x-y; } } } } int main() { scanf("%d%d",&N,&M); for(int i=0;i<=N;i++) scanf("%d",&p[i]); for(int i=0;i<=M;i++) scanf("%d",&q[i]); for(int i=0;i<=N;i++) a[i]=p[i]; for(int i=0;i<=M;i++) b[i]=q[i]; while(limit<=N+M) limit<<=1,l++; for(int i=0;i<limit;i++) r[i]= ( r[i>>1]>>1 )| ( (i&1)<<(l-1) ) ; DFT(a); DFT(b); for(int i=0;i<=limit;i++) a[i]=a[i]*b[i]; IDFT(a); for(int i=0;i<=N+M;i++) printf("%d ",(int)(a[i].x/limit+0.5)); return 0; }
FFT版高精度乘法:
#include<stdio.h> #include <algorithm> #include<math.h> #include <string.h> using namespace std; const double Pi=acos(-1.0); char s1[100010],s2[100010]; int sum[100010]; struct complex { double x,y; complex (double xx=0,double yy=0){x=xx,y=yy;} }a[100010],b[100010]; complex operator + (complex a,complex b){ return complex(a.x+b.x , a.y+b.y);} complex operator - (complex a,complex b){ return complex(a.x-b.x , a.y-b.y);} complex operator * (complex a,complex b){ return complex(a.x*b.x-a.y*b.y , a.x*b.y+a.y*b.x);} int N,M,L; int len=1; int l,r[100010]; int limit=1; void DFT(complex *A,int limit) { for(int i=0;i<limit;i++) if(i<r[i]) swap(A[i],A[r[i]]); for(int mid=1;mid<limit;mid<<=1) { complex Wn( cos(Pi/mid) ,sin(Pi/mid) ); for(int R=mid<<1,j=0;j<limit;j+=R) { complex w(1,0); for(int k=0;k<mid;k++,w=w*Wn) { complex x=A[j+k],y=w*A[j+mid+k]; A[j+k]=x+y; A[j+mid+k]=x-y; } } } if(type==-1)for(int i=0;i<limit;i++)A[i].x/=limit; } void IDFT(complex *A,int limit) { for(int i=0;i<limit;i++) if(i<r[i]) swap(A[i],A[r[i]]); for(int mid=1;mid<limit;mid<<=1) { complex Wn( cos(Pi/mid) ,-1.0*sin(Pi/mid) ); for(int R=mid<<1,j=0;j<limit;j+=R) { complex w(1,0); for(int k=0;k<mid;k++,w=w*Wn) { complex x=A[j+k],y=w*A[j+mid+k]; A[j+k]=x+y; A[j+mid+k]=x-y; } } } if(type==-1)for(int i=0;i<limit;i++)A[i].x/=limit; } int main() { scanf("%s",s1); scanf("%s",s2); int len1=strlen(s1); int len2=strlen(s2); int lenx=len1+len2; for(len=1;len<lenx;len<<=1) L++; for(int i=0;i<len;i++) r[i]=((r[i>>1])>>1)|((i&1)<<(L-1)); for(int i=0;i<len1;i++) a[i]=complex(s1[len1-i-1]-‘0‘,0); for(int i=len1;i<len;i++) a[i]=complex(0,0); for(int i=0;i<len2;i++) b[i]=complex(s2[len2-i-1]-‘0‘,0); for(int i=len2;i<len;i++) b[i]=complex(0,0); DFT(a,len);DFT(b,len); for(int i=0;i<len;i++) a[i]=a[i]*b[i]; IDFT(a,len); for(int i=0;i<len;i++) sum[i]=int(a[i].x+0.5); for(int i=0;i<len;i++) { sum[i+1]+=sum[i]/10; sum[i]%=10; } len=len1+len2-1; while(sum[len]<=0 && len>0) len--; for(int i=len;i>=0;i--) printf("%c",sum[i]+‘0‘); return 0; }
以上是关于FFT各种模板的主要内容,如果未能解决你的问题,请参考以下文章