其他分享
首页 > 其他分享> > 多项式全家桶

多项式全家桶

作者:互联网

放个板子

#include<bits/stdc++.h>
#define ll long long
#define cri const register int
#define re register
#define int ll
#define cp const cplx
using namespace std;
#define vcp vector<cplx>
#define vdb vector<double>
#define vnt vector<int>
#define cp const cplx
#define rs(x) x.resize(bin) 
#define P 3.141592653589793L
const int lim=(1<<15);
const int mod=998244353;
inline void db(vnt &a,cri bin){ for(int i=0;i<bin;i++) cout<<a[i]<<" "; puts(""); }
inline ll qpow(ll a,ll b,ll ans=1){
    for(;b;b>>=1,a=a*a%mod) if(b&1) ans=ans*a%mod;
    return ans;
}
inline void rnt(vnt &A,cri bin){ rs(A);for(int i=0;i<bin;i++) A[i]=0; }
inline int r(double x){ return (int)(x+0.5); }
inline int mo(cri x){ return x>=mod?x-mod:x; }
struct cplx{
    double rl,ig;
    cplx(double r=0,double i=0){ this->rl=r;this->ig=i; }
    friend cplx operator + (const cplx &a,const cplx &b){
        return cplx(a.rl+b.rl,a.ig+b.ig);
    }
    friend cplx operator - (const cplx &a,const cplx &b){
        return cplx(a.rl-b.rl,a.ig-b.ig);
    }
    friend cplx operator * (const cplx &a,const cplx &b){
        return cplx(a.rl*b.rl-a.ig*b.ig,a.rl*b.ig+b.rl*a.ig);
    }
};
vcp ww[19];
struct node{
    inline void clear(vnt &A,cri len,cri bin){ for(int i=len;i<bin;i++) A[i]=0; }
    inline void ntt(vnt &A,cri bin,cri opt){
        vnt v;rnt(v,bin);
        for(int i=0;i<bin;i++) v[i]=v[i>>1]>>1|(i&1?bin>>1:0);
        for(int i=0;i<bin;i++) if(i<v[i]) swap(A[i],A[v[i]]);
        for(int i=1;i<bin;i<<=1){
            const ll wn=qpow(3,opt*(mod-1)/(i<<1)+mod-1);
            for(int j=0,w=1;j<bin;j+=(i<<1),w=1)
                for(int k=0;k<i;k++,w=w*wn%mod) {
                    ll x=A[j+k],y=w*A[j+k+i]%mod;
                    A[j+k]=mo(x+y);A[j+k+i]=mo(x-y+mod);
                }
        }
        if(opt==-1) for(int i=0,pw=qpow(bin,mod-2);i<bin;i++) A[i]=A[i]*pw%mod;
    }
    inline void fft(vcp &A,cri bin,cri opt){
        vnt v;rnt(v,bin);
        for(int i=0;i<bin;i++) v[i]=v[i>>1]>>1|(i&1?bin>>1:0);
        for(int i=0;i<bin;i++) if(i<v[i]) swap(A[i],A[v[i]]);
        for(int i=1,g=0;i<bin;i<<=1,g++)
            for(int j=0;j<bin;j+=(i<<1))
                for(int k=0;k<i;k++){
                    cp x=A[j+k],y=ww[g][k]*A[j+k+i];
                    A[j+k]=x+y;A[j+k+i]=x-y;
                }
        if(opt==1) return;
        reverse(A.begin()+1,A.begin()+bin);
        for(int i=0;i<bin;i++) A[i].rl/=bin;
    }
    inline void mul(vnt &A,vnt &B,cri bin,cri opt){
        if(!opt){   
            ntt(A,bin,1);ntt(B,bin,1);
            for(int i=0;i<bin;i++) A[i]=A[i]*B[i]%mod;
            ntt(A,bin,-1);ntt(B,bin,-1);
        }
        else {
            vcp p1,p2,p3,p4;rs(p1);rs(p2);rs(p3);rs(p4);
            for(int i=0;i<bin;i++)
                p1[i]=cplx(A[i]>>15,0),p2[i]=cplx(A[i]&(lim-1),0),
                p3[i]=cplx(B[i]>>15,0),p4[i]=cplx(B[i]&(lim-1),0);
            fft(p2,bin,1);fft(p4,bin,1);fft(p3,bin,1);fft(p1,bin,1);
            for(int i=0;i<bin;i++){
                const cplx a=p1[i],b=p2[i],c=p3[i],d=p4[i];
                p1[i]=a*c;p2[i]=(b*c)+(a*d);p3[i]=d*b;
            }
            fft(p3,bin,-1);fft(p1,bin,-1);fft(p2,bin,-1);
            for(int i=0;i<bin;i++)
                A[i]=(r(p1[i].rl)%mod*lim%mod*lim%mod+r(p2[i].rl)%mod*lim%mod+r(p3[i].rl))%mod;
        }
    }
    void inv(vnt &A,vnt &B,cri len,cri opt){
        if(len==1) return B[0]=qpow(A[0],mod-2),void();
        inv(A,B,len+1>>1,opt);
        int bin=1;
        while(bin<len+len) bin<<=1;
        vnt t1,t2;rnt(t1,bin);rnt(t2,bin);
        for(int i=0;i<len;i++) t1[i]=A[i],t2[i]=B[i];
        clear(B,len,bin);
        mul(t1,t2,bin,opt); 
        clear(t1,len,bin);
        mul(t1,t2,bin,opt);
        for(int i=0;i<len;i++) B[i]=(B[i]*2-t1[i]+mod)%mod;
    }
    void sqrt(vnt &A,vnt &B,cri len,cri opt){
        if(len==1) return B[0]=1,void();
        sqrt(A,B,len+1>>1,opt);
        int bin=1;
        while(bin<len+len) bin<<=1;
        vnt t3,t4,tmp;rnt(t3,bin);rnt(t4,bin);rnt(tmp,bin);
        for(int i=0;i<len;i++) t3[i]=A[i],t4[i]=B[i];
        clear(B,len,bin);
        inv(t4,tmp,len,opt);
        mul(t3,tmp,bin,opt);
        for(int i=0,p=qpow(2,mod-2);i<len;i++) B[i]=(t3[i]+B[i])*p%mod;
    }
    inline void dao(vnt &A,vnt &B,cri bin){ 
        for(int i=1;i<bin;i++) B[i-1]=A[i]*i%mod;B[bin-1]=0; 
    }
    inline void jifen(vnt &A,vnt &B,cri bin){
        for(int i=1;i<bin-1;i++) B[i]=A[i-1]*qpow(i,mod-2)%mod;B[0]=0;
    }
    inline void ln(vnt &A,vnt &B,cri len,cri opt,int bin=1){
        while(bin<len+len) bin<<=1;
        vnt t5,t6;rnt(t5,bin);rnt(t6,bin);
        inv(A,t5,len,opt);
        dao(A,t6,bin);;
        mul(t5,t6,bin,opt);
        jifen(t5,B,bin);
    }
    void exp(vnt &A,vnt &B,cri len,cri opt,int bin=1){
        if(len==1) return B[0]=1,void();
        exp(A,B,len+1>>1,opt);
        while(bin<len+len) bin<<=1;
        vnt t7;rnt(t7,bin);
        clear(B,len,bin);
        ln(B,t7,len,opt);
        for(int i=0;i<len;i++) t7[i]=mo(A[i]-t7[i]+mod);t7[0]++;
        mul(B,t7,bin,opt);clear(B,len,bin);
    }
    void pw(vnt &A,vnt &B,cri k,cri len,cri opt,int bin=1){
        while(bin<len<<1) bin<<=1;
        vnt t8;rnt(t8,bin);
        ln(A,t8,len,opt);
        for(int i=0;i<len;i++) t8[i]=t8[i]*k%mod;
        exp(t8,B,len,opt);
    }
}ntt;
vnt a,b;
inline int read(re int a=0,re char ch=getchar()){
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') a=((a<<3)+(a<<1)+(ch^48))%mod,ch=getchar();
    return a;
}
signed main(){
    return 0;
}

标签:bin,const,int,多项式,全家,cplx,ig,define
来源: https://www.cnblogs.com/mikufun-hzoi-cpp/p/12073489.html