多项式$fft$,$ntt$,$fwt$初步
Posted 2018hzoicyf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多项式$fft$,$ntt$,$fwt$初步相关的知识,希望对你有一定的参考价值。
最近在学多项式和生成函数。
上课听$lnc$大神讲还是$mengbier$。
作为多项式的前置芝士,$fft,ntt$等是必学的。
在此记录一些关于$fft,ntt,fwt$的知识及例题。。。
FFT:
应用在处理$sum _{i+j=k} f[i]*g[j]$的卷积上。
看网上大佬的博客,基本入了门吧。
自己的关于原理的一些见解:
多项式有系数表示和点值表示,两种表示方法可以相互转化。
FFT可以在$O(n*longn)$内解决多项式乘法。
具体是,点值表示的方法应用在多项式上是$O(n)$的。
那么如果能在快速时间内将多项式表示成点值,然后$O(n)$处理,再转化成多项式岂不美哉。
于是可一取单位根作为代入多项式的$x$,用分治算法处理即可。
板子:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #define MAXN 362144 5 using namespace std; 6 const double PI=acos(-1); 7 struct Cp{ 8 double x,y; 9 Cp(double xx=0,double yy=0){x=xx;y=yy;return ; } 10 friend Cp operator +(Cp a,Cp b){return Cp(a.x+b.x,a.y+b.y); } 11 friend Cp operator -(Cp a,Cp b){return Cp(a.x-b.x,a.y-b.y); } 12 friend Cp operator *(Cp a,Cp b){return Cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x); } 13 }a[MAXN],b[MAXN]; 14 int n,m; 15 int lim=1,l=-1; 16 int ys[MAXN]; 17 inline void FFT(Cp *x,const int &lim,const int &type){ 18 for(int i=0;i<lim;++i)if(i<ys[i])swap(x[i],x[ys[i]]); 19 for(int i=1;i<lim;i<<=1){ 20 Cp tmp(cos(PI/i),sin(PI/i)*type); 21 for(int j=0,I=i<<1;j<lim;j+=I){ 22 Cp w(1,0); 23 for(int k=0;k<i;++k,w=w*tmp){ 24 Cp t1=x[j+k],t2=w*x[k+i+j]; 25 x[j+k]=t1+t2,x[k+i+j]=t1-t2; 26 } 27 } 28 } 29 return ; 30 } 31 int main(){ 32 //freopen("da.in","r",stdin); 33 34 scanf("%d%d",&n,&m); 35 for(int i=0;i<=n;++i)scanf("%lf",&a[i].x); 36 for(int i=0;i<=m;++i)scanf("%lf",&b[i].x); 37 n+=m; 38 for(;lim<=n;lim<<=1,++l); 39 for(int i=0;i<lim;++i)ys[i]=(ys[i>>1]>>1)|((i&1)<<l); 40 FFT(a,lim,1);FFT(b,lim,1); 41 for(int i=0;i<lim;++i)a[i]=a[i]*b[i]; 42 FFT(a,lim,-1); 43 for(int i=0;i<=n;++i)printf("%d ",(int)(a[i].x/lim+0.5)); 44 puts(""); 45 46 return 0; 47 }
NTT:
原理和$FFT$一样。
1 #include<cstdio> 2 #include<iostream> 3 #define MAXN 2197152 4 #define LL long long 5 #define swap(x,y) (x^=y,y^=x,x^=y) 6 using namespace std; 7 const LL mod=998244353; 8 const LL G=3,inv_G=332748118; 9 int n,m; 10 int lim=1,l=-1; 11 int ys[MAXN]; 12 LL a[MAXN],b[MAXN]; 13 LL qpow(LL a,LL b){ 14 LL res=1LL;a%=mod; 15 for(;b;b>>=1,a=a*a%mod)if(b&1)res=res*a%mod; 16 return res%mod; 17 } 18 inline void NTT(LL *x,const int lim,const int type){ 19 for(int i=0;i<lim;++i)if(i<ys[i])swap(x[i],x[ys[i]]); 20 for(int i=1;i<lim;i<<=1){ 21 const int delta=i<<1; 22 const LL tmp=qpow(type==1?G:inv_G,(mod-1)/delta); 23 for(int j=0;j<lim;j+=delta){ 24 LL w=1LL; 25 for(int k=0;k<i;++k,w=w*tmp%mod){ 26 LL t1=x[j+k],t2=w*x[i+j+k]%mod; 27 x[j+k]=(t1+t2)%mod,x[i+j+k]=(t1-t2+mod)%mod; 28 } 29 } 30 } 31 return ; 32 } 33 int main(){ 34 //freopen("da.in","r",stdin); 35 36 scanf("%d%d",&n,&m); 37 for(int i=0;i<=n;++i)scanf("%lld",&a[i]); 38 for(int i=0;i<=m;++i)scanf("%lld",&b[i]); 39 n+=m;for(;lim<n+2;lim<<=1,++l); 40 for(int i=0;i<lim;++i)ys[i]=(ys[i>>1]>>1)|((i&1)<<l); 41 NTT(a,lim,1);NTT(b,lim,1); 42 for(int i=0;i<lim;++i)a[i]=a[i]*b[i]%mod; 43 NTT(a,lim,-1); 44 LL _inv=qpow(lim,mod-2); 45 for(int i=0;i<=n;++i)printf("%lld ",a[i]*_inv%mod); 46 puts(""); 47 48 return 0; 49 }
以上是关于多项式$fft$,$ntt$,$fwt$初步的主要内容,如果未能解决你的问题,请参考以下文章