嫖的模板,原理未知,用于多项式乘法。
将a多项式的系数赋值给a[i].x,b多项式的系数赋值给b[i].x然后solve(n,m)即可。
FFT模板(未初始化)
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int MAX_N=10100000;
const double Pi=acos(-1.0);
inline int read(){
char c=getchar();
int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct complex{
double x,y;
complex(double xx=0,double yy=0){x=xx,y=yy;}
}a[MAX_N],b[MAX_N];
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 l,r[MAX_N];
int limit=1;
void FFT(complex *A,int type){
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),type*sin(Pi/mid)); //单位根
for(int R=mid<<1,j=0;j<limit;j+=R){ //R是区间的长度,j表示前已经到哪个位置了
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 solve(int n,int m){//a[i].x/limit+0.5的int型就是多项式乘法后x^i的系数
limit=1;
while(limit<=n+m){
limit<<=1,l++;
}
for(int i=0;i<limit;i++)
r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
FFT(a,1);
FFT(b,1);
for(int i=0;i<=limit;i++)
a[i]=a[i]*b[i];
FFT(a,-1);
}
int main(void){
int n,m,i,x;
n=read();m=read();
for(i=0;i<=n;i++)
a[i].x=read();
for(i=0;i<=m;i++)
b[i].x=read();
solve(n,m);
for(i=0;i<=n+m;i++){
printf("%d",(int)(a[i].x/limit+0.5));
if(i!=n+m)
printf(" ");
else
printf("\n");
}
return 0;
}
NTT模板(适用于MOD为998244353)
已经初始化
每次使用前记住把a数组和b数组都情况,如果a数组和b数组是a[i]+=x的话!!!
#include<iostream>
#include<cstdio>
using namespace std;
const int MAX_N=3*1010000;
const int MOD=998244353;
const int G=3;
const int Gi=332748118;
inline int read(){
char c=getchar();
int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int limit=1,L,r[MAX_N];
long long a[MAX_N],b[MAX_N];
inline long long pow_mod(long long a,long long n,long long m){
long long ans=1;
while(n){
if(n&1){
ans=(ans*a)%m;
}
a=(a*a)%m;
n>>=1;
}
return ans;
}
inline void NTT(long long *A,int type) {
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){
long long Wn=pow_mod(type==1?G:Gi,(MOD-1)/(mid<<1),MOD);
for(int j=0;j<limit;j+=(mid<<1)){
long long w=1;
for(int k=0;k<mid;k++,w=(w*Wn)%MOD){
int x=A[j+k],y=w*A[j+k+mid]%MOD;
A[j+k]=(x+y)%MOD,
A[j+k+mid]=(x-y+MOD)%MOD;
}
}
}
}
void solve(int n,int m){//a[i]即为多项式乘法后x^i对MOD取模后的系数
limit=1;
L=0;
while(limit<=n+m){
limit<<=1,L++;
}
for(int i=0;i<limit;i++)
r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
for(int i=n+1;i<limit;i++)
a[i]=0;
for(int i=m+1;i<limit;i++)
b[i]=0;
NTT(a,1);
NTT(b,1);
for(int i=0;i<limit;i++)
a[i]=(a[i]*b[i])%MOD;
NTT(a,-1);
long long inv=pow_mod(limit,MOD-2,MOD);
for(int i=0;i<=n+m;i++)
a[i]=a[i]*inv%MOD;
}
int main(void){
int n,m,i;
n=read();m=read();
for(i=0;i<=n;i++)
a[i]=(read()+MOD)%MOD;
for(i=0;i<=m;i++)
b[i]=(read()+MOD)%MOD;
solve(n,m);
for(i=0;i<=n+m;i++)
cout<<a[i]<<" ";
return 0;
}