【洛谷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",&deg1,&deg2,&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; 
}           

  

posted @ 2019-11-23 13:59  EM-LGH  阅读(142)  评论(0编辑  收藏  举报