• 【洛谷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; 
    }           
    

      

  • 相关阅读:
    JAVA地址通过百度地图API转化为经纬度
    JS验证手机号
    JAVA获取六位随机数
    JS判断是否为“YYYYMMDD”式的日期
    JAVA 通过url下载图片保存到本地
    JAVA汉字转拼音
    JS判断是否是苹果系统(ios)和安卓系统(Android)客户端
    JAVA获取请求链接中所有参数(GET请求)
    如何高效学习 Kubernetes 知识图谱?
    当云原生遇到混合云:如何实现“求变”与“求稳”的平衡
  • 原文地址:https://www.cnblogs.com/guangheli/p/11917733.html
Copyright © 2020-2023  润新知