快速数论变换(Number-Theoretic Transformation)

听说NOIP要考NTT于是赶快学了一发(大雾)。

Part.1 多项式卷积

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
typedef long long LL;

inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x;
}

const int MAXN=2100005;
const LL p=998244353,g=3,invg=332748118;
int n,m,l,rev[MAXN];
LL a[MAXN],b[MAXN],inv;

inline LL qpow(LL x,LL y){
    LL ret=1,t=x%p;
    while(y){
        if(y&1) ret=ret*t%p;
        t=t*t%p;
        y>>=1;
    }
    return ret;
}

inline void NTT(LL* c,int dft){
    for(int i=0;i<n;i++)
        if(i<rev[i]) std::swap(c[i],c[rev[i]]);
    for(int mid=1;mid<n;mid<<=1){
        int r=(mid<<1);LL u=qpow(dft>0?g:invg,(p-1)/r);
        for(int l=0;l<n;l+=r){
            LL v=1;
            for(int i=0;i<mid;i++,v=v*u%p){
                LL x=c[l+i],y=v*c[l+mid+i]%p;
                c[l+i]=(x+y<p?x+y:x+y-p);
                c[l+mid+i]=(x-y<0?x-y+p:x-y);
            }
        }
    }
    if(dft<0) for(int i=0;i<n;i++)
        c[i]=c[i]*inv%p;
}
                
int main(){
    n=read(),m=read();
    for(int i=0;i<=n;i++) a[i]=read();
    for(int i=0;i<=m;i++) b[i]=read();
    for(m+=n,n=1;n<=m;n<<=1) l++;
    inv=qpow(n,p-2);
    for(int i=0;i<n;i++) rev[i]=((rev[i>>1]>>1)|((i&1)<<(l-1)));
    NTT(a,1);NTT(b,1);
    for(int i=0;i<n;i++) a[i]=a[i]*b[i]%p;
    NTT(a,-1);
    for(int i=0;i<=m;i++) printf("%lld ",a[i]);
    printf("\n");
    return 0;
}

Reference:https://riteme.github.io/blog/2016-8-22/ntt.html

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9708335.html