板子
#include<bits/stdc++.h>
using namespace std;
#define in Read()
#define int long long
inline int in{
int i=0,f=1;char ch=0;
while(ch!='-'&&!isdigit(ch)) ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int NNN=1e7+5;
const double pi=acos(-1);
int n,m,rot[NNN];
struct Complex{
double x,y;
Complex(double _x=0,double _y=0){x=_x,y=_y;}
friend inline Complex operator + (const Complex u,const Complex v){return Complex(u.x+v.x,u.y+v.y);}
friend inline Complex operator - (const Complex u,const Complex v){return Complex(u.x-v.x,u.y-v.y);}
friend inline Complex operator * (const Complex u,const Complex v){return Complex(u.x*v.x-u.y*v.y,u.x*v.y+v.x*u.y);}
}A[NNN],B[NNN],C[NNN];
inline void FFT(Complex *f,int lim,int sgn){
for(int i=0;i<lim;++i)
if(i<rot[i]) swap(f[i],f[rot[i]]);
for(int siz=2;siz<=lim;siz<<=1){
int len=siz>>1;
Complex wn(cos(2*pi/siz),sgn*sin(2*pi/siz));
for(int l=0;l<lim;l+=siz){
Complex w(1,0);
for(int i=l;i<l+len;++i){
Complex tmp=w*f[i+len];
f[i+len]=f[i]-tmp;
f[i]=f[i]+tmp;
w=w*wn;
}
}
}
}
signed main(){
n=in,m=in;
for(int i=0;i<=n;++i) A[i].x=in;
for(int i=0;i<=m;++i) B[i].x=in;
int lim=1;
while(lim<=n+m) lim<<=1;
for(int i=0;i<lim;++i) rot[i]=((rot[i>>1]>>1)|((i&1)?lim>>1:0));
FFT(A,lim,1);
FFT(B,lim,1);
for(int i=0;i<=lim;++i) C[i]=A[i]*B[i];
FFT(C,lim,-1);
for(int i=0;i<=m+n;++i) printf("%lld ",(int)(C[i].x/lim+0.49));
return 0;
}
註釋版
#include<bits/stdc++.h>
using namespace std;
#define in Read()
#define int long long
inline int in{
int i=0,f=1;char ch=0;
while(ch!='-'&&!isdigit(ch)) ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int NNN=1e7+5;
const double pi=acos(-1);
int n,m,rot[NNN];
struct Complex{
double x,y;
Complex(double _x=0,double _y=0){x=_x,y=_y;}
friend inline Complex operator + (const Complex u,const Complex v){return Complex(u.x+v.x,u.y+v.y);}
friend inline Complex operator - (const Complex u,const Complex v){return Complex(u.x-v.x,u.y-v.y);}
friend inline Complex operator * (const Complex u,const Complex v){return Complex(u.x*v.x-u.y*v.y,u.x*v.y+v.x*u.y);}
}A[NNN],B[NNN],C[NNN];
inline void FFT(Complex *f,int lim,int sgn){
for(int i=0;i<lim;++i)
if(i<rot[i]) swap(f[i],f[rot[i]]);//迭代,一步到位
for(int siz=2;siz<=lim;siz<<=1){//合併項數
int len=siz>>1;//合併區間半長度
Complex wn(cos(2*pi/siz),sgn*sin(2*pi/siz));//合併siz項,用siz次單位根
for(int l=0;l<lim;l+=siz){//區間起點
Complex w(1,0);
for(int i=l;i<l+len;++i){
Complex tmp=w*f[i+len];
f[i+len]=f[i]-tmp;
f[i]=f[i]+tmp;
w=w*wn;
}
}
}
}
signed main(){
n=in,m=in;
for(int i=0;i<=n;++i) A[i].x=in;
for(int i=0;i<=m;++i) B[i].x=in;
int lim=1;
while(lim<=n+m) lim<<=1;//得到2的整次冪
for(int i=0;i<lim;++i) rot[i]=((rot[i>>1]>>1)|((i&1)?lim>>1:0));//注意運算優先級,多打括號
FFT(A,lim,1);
FFT(B,lim,1);
for(int i=0;i<=lim;++i) C[i]=A[i]*B[i];
FFT(C,lim,-1);
for(int i=0;i<=m+n;++i) printf("%lld ",(int)(C[i].x/lim/*注意除數*/+0.49));//得到準確值
return 0;
}
Tips:
- 以
for(int i=0;i<=lim;++i) C[i]=A[i]*B[i];
爲例:注意範圍
在lim
範圍內FFT
,點值就有lim+1
個