非递归版FFT
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e6+5;
inline int read()
{
int x=0;
char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
return x;
}
const double pi=acos(-1.0);
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 fast_fast_tle(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;
}
}
}
}
int main()
{
int N=read(),M=read();
for(int i=0; i<=N; i++) a[i].x=read();
for(int i=0; i<=M; i++) b[i].x=read();
while(limit<=N+M) limit<<=1,l++;
for(int i=0; i<limit; i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)) ;
// 在原序列中 i 与 i/2 的关系是 : i可以看做是i/2的二进制上的每一位左移一位得来
// 那么在反转后的数组中就需要右移一位,同时特殊处理一下奇数
fast_fast_tle(a,1);
fast_fast_tle(b,1);
for(int i=0; i<=limit; i++) a[i]=a[i]*b[i];
fast_fast_tle(a,-1);
for(int i=0; i<=N+M; i++) printf("%d ",(int)(a[i].x/limit+0.5));
}
NTT模板
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define RG register
#define MAX 3000000
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
const int pr=3;
const int MOD=998244353;
const int phi=MOD-1;
int n,m,r[MAX],l;
int a[MAX],b[MAX];
int fpow(int a,int b)
{
int s=1;
while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
return s;
}
void NTT(int *P,int opt)
{
for(int i=0;i<n;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<n;i<<=1)
{
int W=fpow(pr,phi/(i<<1));
for(int p=i<<1,j=0;j<n;j+=p)
{
int w=1;
for(int k=0;k<i;++k,w=1ll*w*W%MOD)
{
int X=P[j+k],Y=1ll*w*P[i+j+k]%MOD;
P[j+k]=(X+Y)%MOD;P[i+j+k]=(X-Y+MOD)%MOD;
}
}
}
if(opt==-1)reverse(&P[1],&P[n]);
}
int main()
{
n=read();m=read();
for(int i=0;i<=n;++i)a[i]=read();
for(int i=0;i<=m;++i)b[i]=read();
m+=n;
for(n=1;n<=m;n<<=1)++l;
for(int i=0;i<n;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
NTT(a,1);NTT(b,1);
for(int i=0;i<n;++i)a[i]=1ll*a[i]*b[i]%MOD;
NTT(a,-1);
int inv=fpow(n,MOD-2);
for(int i=0;i<n;++i)a[i]=1ll*a[i]*inv%MOD;
for(int i=0;i<=m;++i)printf("%d ",a[i]);puts("");
return 0;
}
FWT模板
源自yyq的版本稍作修改
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD=1e9+7;
const int inv2=5e8+4;
int powmod(int a,int b)
{
int ans=1;
while(b)
{
if(b&1) ans=(1ll*ans*a)%MOD;
a=(1ll*a*a)%MOD;
b>>=1;
}
return ans;
}
void FWT_or(int *a,int n,int opt)
{
while((n&-n)!=n) n+=(n&-n);
for(int i=1; i<n; i<<=1)
for(int p=i<<1,j=0; j<n; j+=p)
for(int k=0; k<i; ++k)
if(opt==1)a[i+j+k]=(a[j+k]+a[i+j+k])%MOD;
else a[i+j+k]=(a[i+j+k]+MOD-a[j+k])%MOD;
}
void FWT_and(int *a,int n,int opt)
{
while((n&-n)!=n) n+=(n&-n);
for(int i=1; i<n; i<<=1)
for(int p=i<<1,j=0; j<n; j+=p)
for(int k=0; k<i; ++k)
if(opt==1)a[j+k]=(a[j+k]+a[i+j+k])%MOD;
else a[j+k]=(a[j+k]+MOD-a[i+j+k])%MOD;
}
void FWT_xor(int *a,int n,int opt)
{
while((n&-n)!=n) n+=(n&-n);
for(int i=1; i<n; i<<=1)
for(int p=i<<1,j=0; j<n; j+=p)
for(int k=0; k<i; ++k)
{
ll X=a[j+k],Y=a[i+j+k];
a[j+k]=(X+Y)%MOD;
a[i+j+k]=(X+MOD-Y)%MOD;
if(opt==-1) a[j+k]=1ll*a[j+k]*inv2%MOD,a[i+j+k]=1ll*a[i+j+k]*inv2%MOD;
}
}