Fast Fourier transform

namespace NTT
{
    const int mod=119<<23|1; //998244353
    const int g=3;           //原根
    int wn[25];              //顺时针旋转因子
    int wr[25];              //逆时针旋转因子
    int inv[25];             //2^i的逆元

    void init()
    {
        inv[0]=wr[1]=1;
        inv[1]=mod-mod/2;
        for(int i=2;i<=23;++i)
            inv[i]=md(1ll*inv[i-1]*inv[1]);
        wn[23]=15311432;    //qpow(3,119)
        wr[23]=469870224;   //inv[wn[23]]
        for(int i=22;i>=1;--i)
        {
            wn[i]=1ll*wn[i+1]*wn[i+1]%mod;
            wr[i]=1ll*wr[i+1]*wr[i+1]%mod;
        }
    }

    void ntt(ll xs[],int m,int logm,bool dft=true)
    {
        int invm=inv[logm];
        for(int i=0,j=m>>1,k=0;ii)swap(xs[k],xs[i]);
            while(k&j)k^=j,j>>=1;
            k|=j,j=m>>1;
        }
        for(int i=1,rat=2;rat<=m;++i,rat<<=1)
        {
            int l=rat>>1,w=dft?wn[i]:wr[i];
            for(int j=0,wx=1;j

多项式乘法

struct Polynomial
{
    static const int __=2.7e5;        //>2^(logn+2);
    static const int mod=119<<23|1; //998244353
    static const int g=3;           //原根
    static int wn[25];              //顺时针旋转因子
    static int wr[25];              //逆时针旋转因子
    static int inv[25];             //2^i的逆元

    static ll md(ll x)
    {
        if(x<=-mod || x>=mod)
            x%=mod;
        if(x<0)x+=mod;
        return x;
    }

    static ll qpow(ll x,ll y)
    {
        ll res=1;
        for(;y;y>>=1,x=md(x*x))
            if(y&1)res=md(res*x);
        return res;
    }

    static void init()
    {
        inv[0]=wr[1]=1;
        inv[1]=mod-mod/2;
        for(int i=2;i<=23;++i)
            inv[i]=md(1ll*inv[i-1]*inv[1]);
        wn[23]=15311432;    //qpow(3,119)
        wr[23]=469870224;   //inv[wn[23]]
        for(int i=22;i>=1;--i)
        {
            wn[i]=1ll*wn[i+1]*wn[i+1]%mod;
            wr[i]=1ll*wr[i+1]*wr[i+1]%mod;
        }
    }

    ll a[__];int n;

    Polynomial() {}

    Polynomial(ll b[],int _n) {set(b,_n);}

    void set(int _n){n=_n;}

    void set(ll b[],int _n)
    {
        n=_n;
        for(int i=0;i<=n;++i)
            a[i]=b[i];
        simpfy();
    }

    void simpfy(){for(;n && !a[n];--n);}

    ll& operator[](int x){return a[x];}

    Polynomial operator+(const Polynomial &b)const
    {
        static Polynomial c;
        c.set(max(n,b.n));
        for(int i=0;i<=c.n;++i)
        {
            c[i]=(i<=n?a[i]:0)+(i<=b.n?b.a[i]:0);
            c[i]=md(c[i]);
        }
        c.simpfy();
        return c;
    }

    int m,logm;

    void ntt(ll xs[],bool dft=true)
    {
        int invm=inv[logm];
        for(int i=0,j=m>>1,k=0;ii)swap(xs[k],xs[i]);
            while(k&j)k^=j,j>>=1;
            k|=j,j=m>>1;
        }
        for(int i=1,rat=2;rat<=m;++i,rat<<=1)
        {
            int l=rat>>1,w=dft?wn[i]:wr[i];
            for(int j=0,wx=1;j

你可能感兴趣的:(Fast Fourier transform)