$\text{O}(n \log n)$ 多项式运算

贴个老板子

namespace Modsqrt{
 
    #define ll long long
 
    ll w2;
 
    struct CP{
        ll x,y;
        CP() {}
        CP(ll x,ll y):x(x),y(y) {}
        CP operator *(const CP &a) const{
            ll X=(x*a.x+y*a.y%mod*w2)%mod;
            ll Y=(x*a.y+y*a.x)%mod;
            return CP(X,Y);
        }
    };
 
    inline CP CP_qpow(CP a,int b){
        CP ans=CP(1,0);
        for(;b;b>>=1){
            if(b&1)ans=ans*a;
            a=a*a;
        }
        return ans;
    }
 
    inline ll modsqrt(ll x){
        srand(time(0));
        ll y=1ll*rand()*rand()%mod;
        while(qpow(w2=(y*y+mod-x)%mod,(mod-1)>>1)==1)
            y=1ll*rand()*rand()%mod;
        CP ans=CP_qpow(CP(y,1),(mod+1)>>1);
        return min(ans.x,mod-ans.x);
    }
 
    #undef ll
 
}
 
using namespace Modsqrt;
 
long long inv[maxn],frac[maxn],invf[maxn];
 
inline void Init_Inv(int N){
    frac[0]=1;
    for(int i=1;i<=N;i++)frac[i]=frac[i-1]*i%mod;
    invf[N]=qpow(frac[N],mod-2);
    for(int i=N;i>=1;i--)invf[i-1]=invf[i]*i%mod;
    for(int i=1;i<=N;i++)inv[i]=invf[i]*frac[i-1]%mod;
}
 
inline void init(int N){
    Init_Inv(N);
}
 
namespace Polyn{
 
    #define G 3
 
    #define ll long long
 
    int lstn,rev[maxn];
 
    long long g[2][33];
 
    inline void cpy(int N,ll *a,ll *b){
        for(int i=0;i<N;i++)a[i]=b[i];
    }
 
    inline void clr(int N,ll *a){
        for(int i=0;i<N;i++)a[i]=0;
    }
 
    inline void mve(int N,int len,ll *a){
        if(!len)return;
        if(len>0){
            for(int i=N-1;i>=len;i--)a[i]=a[i-len];
            for(int i=len-1;i>=0;i--)a[i]=0;
        }
        else {
            len=-len;
            for(int i=0;i<N-len;i++)a[i]=a[i+len];
            for(int i=N-len;i<N;i++)a[i]=0;
        }
    }
 
    inline void Init_G(){
        g[0][23]=qpow(G,(mod-1)/(1<<23));
        g[1][23]=qpow(g[0][23],mod-2);
        for(int i=22;i>=1;i--){
            g[0][i]=g[0][i+1]*g[0][i+1]%mod;
            g[1][i]=g[1][i+1]*g[1][i+1]%mod;
        }
    }
 
    inline void init(int N){
        if(lstn==N)return;
        lstn=N;
        for(int i=1;i<N;i++)
            rev[i]=(rev[(i>>1)]>>1)|(i&1?(N>>1):0);
    }
 
    inline void Der(int N,ll *f){
        for(int i=1;i<N;i++)
            f[i-1]=f[i]*i%mod;
        f[N-1]=0;
    }
 
    inline void Int(int N,ll *f){
        for(int i=N;i;i--)
            f[i]=f[i-1]*inv[i]%mod;
        f[0]=0;
    }
 
    inline void NTT(int N,ll *f,bool flg){
        for(int i=1;i<N;i++)
            if(i<rev[i])swap(f[i],f[rev[i]]);
        for(int i=1,lg=1;i<N;i<<=1,lg++){
            for(int p=(i<<1),j=0;j<N;j+=p){
                ll ng=1;
                for(int k=0;k<i;k++){
                    ll val=ng*f[i+j+k]%mod;
                    f[i+j+k]=(f[j+k]+mod-val)%mod;
                    (f[j+k]+=val)%=mod;
                    (ng*=g[flg][lg])%=mod;
                }
            }
        }
        if(!flg)return;
        ll invn=qpow(N,mod-2);
        for(int i=0;i<N;i++)
            (f[i]*=invn)%=mod;
    }
 
    inline void Mul(int n,ll *a,ll b){
        for(int i=0;i<n;i++)(a[i]*=b)%=mod;
    }
 
    inline void Mul(int n,ll *a,ll *b,int na=-1,int nb=-1,int len=-1){
        int N=1;
        for(;N<n;N<<=1);
        init(N);
        if(na<0)na=n;
        if(nb<0)nb=n;
        clr(N-na,a+na),clr(N-nb,b+nb);
        NTT(N,a,0),NTT(N,b,0);
        for(int i=0;i<N;i++)
            (a[i]*=b[i])%=mod;
        NTT(N,a,1);
        if(len<0)return;
        clr(N-len,a+len);
    }
 
    inline void Inv(int n,ll *f,ll *ans){
        static ll A[maxn],B[maxn];
        int N=1;
        for(;N<n;N<<=1);
        clr(N,A),clr(N,B),clr(N,ans);
        ans[0]=qpow(f[0],mod-2);
        for(int len=2;len<=N;len<<=1){
            cpy(len>>1,A,ans);
            cpy(len,B,f);
            Mul(len,A,B);
            clr(len>>1,A);
            cpy(len,B,ans);
            Mul(len,A,B);
            for(int i=(len>>1);i<len;i++)
                ans[i]=(ans[i]*2+mod-A[i])%mod;
        }
    }
 
    inline void Sqrt(int n,ll *f,ll *ans){
        static ll A[maxn],B[maxn];
        int N=1;
        for(;N<n;N<<=1);
        clr(N,A),clr(N,B),clr(N,ans);
        ans[0]=modsqrt(f[0]);
        for(int len=2;len<=N;len<<=1){
            Inv(len,ans,A);
            cpy(len,B,f);
            Mul((len<<1),A,B,len,len,len);
            for(int i=0;i<len;i++)
                ans[i]=(ans[i]+A[i])*inv2%mod;
        }
        clr(N-n,ans+n);
    }
 
    inline void Ln(int n,ll *f,ll *ans){
        static ll A[maxn];
        int N=1;
        for(;N<(n<<1);N<<=1);
        clr(N,A),clr(N,ans);
        cpy(n,ans,f);
        Der(n,ans);
        Inv(n,f,A);
        Mul(n+n-1,ans,A,n);
        Int(n,ans);
    }
 
    inline void Exp(int n,ll *f,ll *ans){
        static ll A[maxn],B[maxn];
        int N=1;
        for(;N<n;N<<=1);
        clr(N,A),clr(N,B),clr(N,ans);
        ans[0]=1;
        for(int len=2;len<=N;len<<=1){
            cpy(len,B,f);
            B[0]++;
            Ln(len,ans,A);
            for(int i=0;i<len;i++)
                (B[i]+=mod-A[i])%=mod;
            Mul((len<<1),ans,B,len,len,len);
        }
        clr(N-n,ans+n);
    }
     
    inline void Pow(int n,int k,int k1,int MOD,ll *f,ll *ans){
        if(n==1)cpy(n,ans,f);
        static ll A[maxn];
        int x=0;
        int N=1;
        for(;N<n;N<<=1);
        clr(N,A),clr(N,ans);
        for(;x<n&&!f[x];x++);
        if(1ll*x*k1>=MOD)return;
        cpy(n,ans,f);
        mve(n,-x,ans);
        int m=MOD-x;
        if(ans[0]>1){
            ll inv0=qpow(ans[0],mod-2);
            for(int i=0;i<n-x;i++)
                (ans[i]*=inv0)%=mod;
        }
        Ln(m,ans,A);
        Mul(m,A,k);
        Exp(m,A,ans);
        mve(MOD,x*k1,ans);
        if(f[x]>1)Mul(MOD,ans,qpow(f[x],k1));
    }
 
    #undef ll
 
    #undef G
 
}
 
long long A[maxn];
 
struct P{
 
    #define ll long long
 
    int n;
 
    ll f[maxn];
 
    inline void Read(){
        for(int i=0;i<n;i++)
            f[i]=read<ll>();
    }
 
    inline void Print(){
        for(int i=0;i<n;i++)
            printf("%lld ",f[i]);
        puts("");
    }
 
    ll& operator [](const int &x){
        return f[x];
    }
 
    inline P Mod(int N){
        P c;
        c.n=N;
        for(int i=0;i<N;i++)
            c[i]=f[i];
        return c;
    }
 
    inline P R(){
        P c;
        c.n=n;
        for(int i=0;i<n;i++)
            c[i]=f[n-i-1];
        return c;
    }
 
    inline P Der(){
        P c;
        c.n=n-1;
        for(int i=1;i<n;i++)
            c[i-1]=f[i]*i%mod;
        return c;
    }
 
    inline P Int(){
        P c;
        c.n=n+1;
        for(int i=1;i<=n;i++)
            c[i]=f[i-1]*inv[i]%mod;
        c[0]=0;
        return c;
    }
 
    inline P Inv(){
        P c;
        c.n=n;
        Polyn::Inv(n,f,c.f);
        return c;
    }
 
    inline P Sqrt(){
        P c;
        c.n=n;
        Polyn::Sqrt(n,f,c.f);
        return c;
    }
 
    inline P Ln(){
        P c;
        c.n=n;
        Polyn::Ln(n,f,c.f);
        return c;
    }
 
    inline P Exp(){
        P c;
        c.n=n;
        Polyn::Exp(n,f,c.f);
        return c;
    }
 
    inline P Pow(int k,int k1,int MOD){
        P c;
        c.n=n;
        Polyn::Pow(n,k,k1,MOD,f,c.f);
        return c;
    }
 
    P operator -(){
        P c;
        c.n=n;
        for(int i=0;i<c.n;i++)c[i]=mod-f[i];
        return c;
    }
 
    P operator +(const ll b){
        P c;
        c.n=n;
        for(int i=0;i<c.n;i++)c[i]=f[i];
        (c[0]+=b)%=mod;
        return c;
    }
 
    P operator +(P b){
        P c;
        c.n=max(n,b.n);
        for(int i=0;i<c.n;i++)
            c[i]=(f[i]+b[i])%mod;
        return c;
    }
 
    P operator -(const ll b){
        P c;
        c.n=n;
        for(int i=0;i<c.n;i++)c[i]=f[i];
        (c[0]+=mod-b%mod)%=mod;
        return c;
    }
     
    P operator -(P b){
        P c;
        c.n=max(n,b.n);
        for(int i=0;i<c.n;i++)
            c[i]=(f[i]+mod-b[i])%mod;
        return c;
    }
 
    P operator *(const ll num){
        P c;
        c.n=n;
        for(int i=0;i<n;i++)
            c[i]=f[i]*num%mod;
        return c;
    }
 
    P operator *(P b){
        P c;
        c.n=n+b.n-1;
        for(int i=0;i<n;i++)c[i]=f[i];
        for(int i=0;i<b.n;i++)A[i]=b[i];
        int N=1;
        for(;N<c.n;N<<=1);
        for(int i=n;i<N;i++)c[i]=0;
        for(int i=b.n;i<N;i++)A[i]=0;
        Polyn::Mul(c.n,c.f,A);
        return c;
    }
 
    #undef ll
 
};
原文地址:https://www.cnblogs.com/wyzwyz/p/15557833.html