【洛谷P4245】 【模板】任意模数NTT
三模数 NTT,感觉不是很难写 $?$
代码借鉴的 https://www.cnblogs.com/Mychael/p/9297652.html
code:
#include <bits/stdc++.h> #define SIZE 400005 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; inline ll qpow(ll x,ll y,ll Mod) { ll re=1ll; for(x%=Mod;y;y>>=1,x=x*x%Mod) if(y&1) re=re*x%Mod; return re; } int pr[3]={469762049,998244353,1004535809}; struct poly { int G,Mod,A[SIZE]; void NTT(int *a,int len,int flag) { int i,j,k,mid; for(i=k=0;i<len;++i) { if(i>k) swap(a[i],a[k]); for(j=len>>1;(k^=j)<j;j>>=1); } for(mid=1;mid<len;mid<<=1) { int wn=qpow(G,(Mod-1)/(mid<<1),Mod); if(flag==-1) wn=qpow(wn,Mod-2,Mod); for(i=0;i<len;i+=mid<<1) { int w=1; for(j=0;j<mid;++j) { int x=a[i+j], y=1ll*w*a[i+j+mid]%Mod; a[i+j]=1ll*(x+y)%Mod, a[i+j+mid]=(x-y+Mod)%Mod; w=1ll*w*wn%Mod; } } } if(flag==-1) { int rev=qpow(len,Mod-2,Mod); for(i=0;i<len;++i) a[i]=1ll*a[i]*rev%Mod; } } }ntt[3]; ll ans[SIZE]; int F[SIZE],G[SIZE],B[SIZE],deg1,deg2,deg,md; ll INV(ll n,ll p) { return qpow(n%p, p-2,p); } ll mul(ll a,ll b,ll p) { ll re=0; for(;b;b>>=1,a=(a+a)%p) if(b&1) re=(re+a)%p; return re; } void CRT() { deg=deg1+deg2; ll a,b,c,t,k,M=1ll*pr[0]*pr[1]; ll inv1=INV(pr[1],pr[0]), inv0=INV(pr[0],pr[1]),inv3=INV(M%pr[2],pr[2]); for(int i=0;i<=deg;++i) { a=ntt[0].A[i]; b=ntt[1].A[i]; c=ntt[2].A[i]; t=(mul(a*pr[1]%M,inv1,M)+mul(b*pr[0]%M,inv0,M))%M; k=((c-t%pr[2])%pr[2]+pr[2])%pr[2]*inv3%pr[2]; ans[i]=((k%md)*(M%md)%md+t%md)%md; } } void conv() { int n=1; while(n<=(deg1+deg2)) n<<=1; for(int u=0;u<=2;++u) { ntt[u].G=3; ntt[u].Mod=pr[u]; for(int i=0;i<=deg1;++i) ntt[u].A[i]=F[i]; for(int i=0;i<=deg2;++i) B[i]=G[i]; for(int i=deg2+1;i<n;++i) B[i]=0; ntt[u].NTT(ntt[u].A,n,1); ntt[u].NTT(B,n,1); for(int i=0;i<n;++i) ntt[u].A[i]=1ll*ntt[u].A[i]*B[i]%pr[u]; ntt[u].NTT(ntt[u].A,n,-1); } } int main() { // setIO("input"); scanf("%d%d%d",°1,°2,&md); for(int i=0;i<=deg1;++i) scanf("%d",&F[i]); for(int i=0;i<=deg2;++i) scanf("%d",&G[i]); conv(); CRT(); for(int i=0;i<=deg;++i) printf("%lld ",ans[i]); return 0; }