快速数论变换NTT模板

Posted 无尽的蓝黄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速数论变换NTT模板相关的知识,希望对你有一定的参考价值。

51nod 1348 乘积之和

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <bitset>
#include <set>
const int maxlongint=2147483647;
const long long mo=100003;
const int N=300005;
using namespace std;
long long mod[2]={998244353,1004535809},M=mod[0]*mod[1];
long long f[N],g[N],f1[N],g1[N],h[22][N],W[2][N],ny;
int a[N],n,q;
long long poww(long long x,int y,int z)
{
    long long s=1;
    for(;y;y>>=1,x=x*x%mod[z]) 
        if(y&1) s=s*x%mod[z];
    return s;
}
long long mul(long long x,int y)
{
    long long s=0;
    for(;y;y>>=1,x=(x+x)%M)
        if(y&1) s=(s+x)%M;
    return s;
}
void NTT(long long *f,int len,int type,int z)
{
    for(int i=0,p=0;i<len;i++)
    {
        if(i<p) swap(f[i],f[p]);
        for(int j=len>>1;(p^=j)<j;j>>=1);
    }
    for(int i=2;i<=len;i<<=1)
    {
        int half=i>>1,pe=len/i;
        for(int j=0;j<half;j++)
        {
            long long w=!type?W[z][pe*j]:W[z][len-pe*j];
            for(int k=j;k<len;k+=i)
            {
                long long x=f[k],y=w*f[k+half]%mod[z];
                f[k]=(x+y)%mod[z],f[k+half]=(x-y+mod[z])%mod[z];
            }
        }
    }
    if(type)
    {
        ny=poww(len,mod[z]-2,z);
        for(int i=0;i<len;i++) f[i]=f[i]*ny%mod[z];
    }
}
long long CRT(int i)
{
    long long x0=poww(mod[1],mod[0]-2,0),x1=poww(mod[0],mod[1]-2,1);
    return (mul(f[i]*mod[1]%M,x0%M)+mul(f1[i]*mod[0]%M,x1%M))%M%mo;
}
void dc(int l,int r,int deep)
{
    if(l==r)
    {
        h[deep][0]=1,h[deep][1]=a[l]%mo;
        return;
    }
    int mid=(l+r)>>1,fn;
    for(fn=1;fn<=r-l+1;fn<<=1);

    dc(l,mid,deep+1);

    for(int i=0;i<fn;i++) h[deep][i]=h[deep+1][i],h[deep+1][i]=0;

    dc(mid+1,r,deep+1);

    W[0][0]=W[1][0]=1,W[0][1]=poww(3,(mod[0]-1)/fn,0),W[1][1]=poww(3,(mod[1]-1)/fn,1);
    for(int i=2;i<=fn;i++) W[0][i]=W[0][i-1]*W[0][1]%mod[0],W[1][i]=W[1][i-1]*W[1][1]%mod[1];

    for(int i=0;i<fn;i++) f[i]=f1[i]=g[i]=g1[i]=0;
    for(int i=0;i<=mid-l+1;i++) f[i]=f1[i]=h[deep][i];
    for(int i=0;i<fn;i++) h[deep][i]=0;
    for(int i=0;i<=r-mid;i++) g[i]=g1[i]=h[deep+1][i];
    for(int i=0;i<fn;i++) h[deep+1][i]=0;

    NTT(f,fn,0,0),NTT(f1,fn,0,1);
    NTT(g,fn,0,0),NTT(g1,fn,0,1);
    for(int i=0;i<fn;i++) f[i]=f[i]*g[i]%mod[0],f1[i]=f1[i]*g1[i]%mod[1];
    NTT(f,fn,1,0),NTT(f1,fn,1,1);

    for(int i=0;i<fn;i++) h[deep][i]=CRT(i);
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    dc(1,n,0);
    for(int x;q--;)
    {
        scanf("%d",&x);
        printf("%lld\n",h[0][x]);
    }
}

以上是关于快速数论变换NTT模板的主要内容,如果未能解决你的问题,请参考以下文章

NTT快速数论变换

NTT(快速数论变换)用到的各种素数及原根

快速数论变换(NTT)

模板NTT

NTT

FFT/NTT/FMT/FWT题目