luogu P4245 模板任意模数NTT MTT

Posted guangheli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; 
}

  

以上是关于luogu P4245 模板任意模数NTT MTT的主要内容,如果未能解决你的问题,请参考以下文章

任意模数NTT(MTT)模板

洛谷 - P4245 模板任意模数多项式乘法(三模NTT+中国剩余定理/五次FFT的MTT)

[题解] Luogu P4245 [模板]任意模数NTT

P4245 模板任意模数多项式乘法(NTT)

MTT:任意模数NTT

MTT 模板(任意模数)