luogu P4245 【模板】任意模数NTT MTT
Code:
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 1000000
#define M 32768
#define double long double
#define ll long long
using namespace std;
namespace poly{
const double pi=acos(-1);
int rev[maxn],l;
struct Cpx{
double x,y;
Cpx (double t1=0,double t2=0){x=t1,y=t2;}
};
Cpx operator+(Cpx a,Cpx b){ return Cpx(a.x+b.x,a.y+b.y);}
Cpx operator-(Cpx a,Cpx b){ return Cpx(a.x-b.x, a.y-b.y); }
Cpx operator*(Cpx a,Cpx b){ return Cpx(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x); }
void FFT(Cpx *a,int n,int flag){
for(int i=0;i<n;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<n;++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int mid=1;mid<n;mid<<=1){
Cpx wn(cos(pi/mid), flag*sin(pi/mid)),x,y;
for(int j=0;j<n;j+=(mid<<1)){
Cpx w(1,0);
for(int k=0;k<mid;++k) {
x=a[j+k],y=w*a[j+mid+k];
a[j+k]=x+y,a[j+mid+k]=x-y, w=w*wn;
}
}
}
if(flag==1) return;
for(int i=0;i<n;++i) a[i].x=a[i].x/(double)n;
}
Cpx a[maxn<<1],b[maxn<<1],c[maxn<<1],d[maxn<<1];
Cpx e[maxn<<1],g[maxn<<1],f[maxn<<1],h[maxn<<1];
int ans[maxn];
void MTT(int n,int m,int *F,int *G,int p){
n+=m,l=0;
for(m=1;m<=n;m<<=1) ++l;
for(int i=0;i<n;++i) {
a[i].x=F[i]/M,b[i].x=F[i]%M;
c[i].x=G[i]/M,d[i].x=G[i]%M;
}
FFT(a,m,1),FFT(b,m,1),FFT(c,m,1),FFT(d,m,1);
for(int i=0;i<m;++i){
e[i]=a[i]*c[i],f[i]=a[i]*d[i];
g[i]=b[i]*c[i],h[i]=b[i]*d[i];
}
FFT(e,m,-1),FFT(f,m,-1),FFT(g,m,-1),FFT(h,m,-1);
for(int i=0;i<m;++i){
ans[i]=(ll)(e[i].x+0.5)%p*M%p*M%p,ans[i]%=p;
ans[i]+=(ll)(f[i].x+0.5)%p*M%p,ans[i]%=p;
ans[i]+=(ll)(g[i].x+0.5)%p*M%p,ans[i]%=p;
ans[i]+=(ll)(h[i].x+0.5)%p;
ans[i]%=p;
}
}
};
int n,m,p;
int A[maxn<<1],B[maxn<<1];
int main(){
//setIO("input");
scanf("%d%d%d",&n,&m,&p);
for(int i=0;i<=n;++i) scanf("%d",&A[i]);
for(int i=0;i<=m;++i) scanf("%d",&B[i]);
poly::MTT(n,m,A,B,p);
for(int i=0;i<=n+m;++i) printf("%d ",poly::ans[i]);
return 0;
}