Luogu 4245: [Template] Arbitrary Modulus NTT - Problem Solving

https://www.luogu.org/problemnew/show/P4245

Given two polynomials, find their product, each coefficient modulo p.

refer to:

Code and partial understanding reference https://www.luogu.org/blog/yhzq/solution-p4245

NTT common modulus https://blog.csdn.net/hnust_xx/article/details/76572828

Something about the NTT presentation.

————————————

The function of NTT is the same as that of DFT, except that NTT can take the modulo, and the precision error is small.

Our only limitation is the prime number p=k*2^n+1 to be modulo, so 998244353 comes into being.

The problem of how to construct so that each transformation will reduce the length by half is related to the original root of p, so I won't talk about it here.

However, when p is uncertain, we can also use the Chinese remainder theorem.

Specifically, find some p1, p2...pk that satisfy the NTT condition, then calculate the results, and finally use the Chinese remainder theorem to eliminate them in turn.

However, the disgusting thing about this question is that it is very likely to explode longlong, and when the modulus is greater than int, it cannot be multiplied quickly. At this time, we must use the fast multiplication proposed by Locke (for details, you can go to the first blog in the reference. )

#include<cstdio>
#include<cctype>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
typedef long double dl;
const int N=5e5+5;
const ll p1=469762049,p2=998244353,p3=1004535809,g=3;
const ll M=p1*p2;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
ll qpow(ll a,ll n,ll p){
    ll res=1;
    while(n){
    if(n&1)res=res*a%p;
    a=a*a%p;n>>=1;
    }
    return res;
}
ll qmulti(ll a,ll b,ll p){
    a%=p,b%=p;
    return ((a*b-(ll)((ll)((dl)a/p*b+0.5)*p))%p+p)%p;
}
void FNT(ll a[],int n,int on,ll p){
    for(int i=1,j=n>>1;i<n-1;i++){
        if(i<j)swap(a[i],a[j]);
        int k=n>>1;
        while(j>=k){j-=k;k>>=1;}
        if(j<k)j+=k;
    }
    for(int i=2;i<=n;i<<=1){
    ll res=qpow(g,(p-1)/i,p);
        for(int j=0;j<n;j+=i){
        ll w=1;
            for(int k=j;k<j+i/2;k++){
                ll u=a[k],t=w*a[k+i/2]%p;
                a[k]=(u+t)%p;
                a[k+i/2]=(u-t+p)%p;
                w=w*res%p;
            }
        }
    }
    if(on==-1){
    ll inv=qpow(n,p-2,p);
    a[0]=a[0]*inv%p;
    for(int i=1;i<=n/2;i++){
        a[i]=a[i]*inv%p;
        if(i!=n-i)a[n-i]=a[n-i]*inv%p;
        swap(a[i],a[n-i]);
    }
    }
}
int n,m,p;
ll a[N],b[N],c[N],d[N],ans[3][N];
int main(){
    n=read(),m=read(),p=read();
    for(int i=0;i<=n;i++)a[i]=read();
    for(int i=0;i<=m;i++)b[i]=read();
    int nn=1;
    while(nn<=n+m)nn<<=1;
    
    memcpy(c,a,sizeof(a));memcpy(d,b,sizeof(b));
    FNT(c,nn,1,p1);FNT(d,nn,1,p1);
    for(int i=0;i<nn;i++)ans[0][i]=c[i]*d[i]%p1;
    memset(c,0,sizeof(c));memset(d,0,sizeof(d));

    memcpy(c,a,sizeof(a));memcpy(d,b,sizeof(b));
    FNT(c,nn,1,p2);FNT(d,nn,1,p2);
    for(int i=0;i<nn;i++)ans[1][i]=c[i]*d[i]%p2;
    memset(c,0,sizeof(c));memset(d,0,sizeof(d));


    memcpy(c,a,sizeof(a));memcpy(d,b,sizeof(b));
    FNT(c,nn,1,p3);FNT(d,nn,1,p3);
    for(int i=0;i<nn;i++)ans[2][i]=c[i]*d[i]%p3;
    memset(c,0,sizeof(c));memset(d,0,sizeof(d));

    FNT(ans[ 0 ],nn, -1 ,p1);
    FNT(ans[1],nn,-1,p2);
    FNT (ans [ 2 ], nn, - 1 , p3);

    for(int i=0;i<=n+m;i++){
    ll A=(qmulti(ans[0][i]*p2%M,qpow(p2%p1,p1-2,p1),M)+
          qmulti(ans[1][i]*p1%M,qpow(p1%p2,p2-2,p2),M))%M;
    ll k=((ans[2][i]-A)%p3+p3)%p3*qpow(M%p3,p3-2,p3)%p3;
    printf("%lld ",((k%p)*(M%p)%p+A%p)%p);
    }
    puts("");
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+ Author of this article: luyouqi233. +

+Welcome to my blog: http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325483932&siteId=291194637