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

原本的板子有点拉胯,贴个少一些操作的快速板子(然而有些清空和封装没做好)

 

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>

#define maxn 3003003

const int G=3,mod=998244353;

template<class T>

inline T read(){
	T r=0,f=0;
	char c;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
	return f?-r:r;
}

inline long long qpow(long long a,int b){
	long long ans=1;
	for(;b;b>>=1){
		if(b&1)(ans*=a)%=mod;
		(a*=a)%=mod;
	}
	return ans;
}

namespace Poly{//Need Init

	int Lst,g[maxn],rev[maxn];

	long long frac[maxn],invf[maxn],inv[maxn];

	inline void Add(int &x,int y){
		x+=y-mod,x+=(x>>31)&mod;
	}

	inline void Sub(int &x,int y){
		x-=y,x+=(x>>31)&mod;
	}

	inline void clr(int *f,int n){
		for(int i=0;i<n;i++)f[i]=0;
	}

	inline void cpy(int *f,int *g,int n){
		for(int i=0;i<n;i++)f[i]=g[i];
	}

	inline void T(int n,int *f){
		std::reverse(f,f+n);
	}

	inline void Der(int n,int *f){
		for(int i=0;i<n-1;i++)
			f[i]=f[i+1]*(i+1ll)%mod;
		f[n-1]=0;
	}

	inline void Int(int n,int *f){
		for(int i=n-1;i;i--)
			f[i]=f[i-1]*inv[i]%mod;
		f[0]=0;
	}

	inline void init(int n){
		frac[0]=1;
		for(int i=1;i<n;i++)
			frac[i]=frac[i-1]*i%mod;
		invf[n-1]=qpow(frac[n-1],mod-2);
		for(int i=n-1;i;i--){
			invf[i-1]=invf[i]*i%mod;
			inv[i]=invf[i]*frac[i-1]%mod;
		}
		int N=1;
		for(;N<n;N<<=1);
		for(int i=1;i<N;i<<=1){
			g[i]=1;
			int p=i<<1;
			long long x=qpow(G,(mod-1)/p);
			for(int j=i+1;j<p;j++)
				g[j]=g[j-1]*x%mod;
		}
	}

	inline void init_rev(int N){
		if(N==Lst)return;
		for(int i=1;i<N;i++)
			rev[i]=(rev[i>>1]>>1)|(i&1?N>>1:0);
		Lst=N;
	}

	inline void NTT(int N,int *f,bool opt){
		static unsigned long long A[maxn];
		for(int i=0;i<N;i++)A[i]=f[rev[i]];
		for(int i=1;i<N;i<<=1)
			for(int j=0,p=i<<1;j<N;j+=p)
				for(int k=0;k<i;k++){
					int l=j|k,r=i|l;
					int val=A[r]*g[i|k]%mod;
					A[r]=A[l]+mod-val,A[l]+=val;
				}
		if(!opt){
			for(int i=0;i<N;i++)
				f[i]=A[i]%mod;
			return;
		}
		int invn=mod-(mod-1)/N;
		f[0]=A[0]%mod*invn%mod;
		for(int i=1;i<N;i++)
			f[i]=A[N-i]%mod*invn%mod;
	}

	int A[maxn],B[maxn],C[maxn],D[maxn];

	inline void Inv(int N,int *f,int *invf){
		invf[0]=qpow(f[0],mod-2);
		for(int len=2;len<=N;len<<=1){
			init_rev(len);
			cpy(A,f,len);
			cpy(B,invf,len>>1);
			NTT(len,A,0),NTT(len,B,0);
			for(int i=0;i<len;i++)
				A[i]=1ll*A[i]*B[i]%mod,B[i]=0;
			NTT(len,A,1),clr(A,len>>1),NTT(len,A,0);
			cpy(B,invf,len>>1),NTT(len,B,0);
			for(int i=0;i<len;i++)
				A[i]=1ll*A[i]*B[i]%mod,B[i]=0;
			NTT(len,A,1),clr(A,len>>1);
			for(int i=len>>1;i<len;i++)
				invf[i]=mod-A[i],A[i]=0;
		}
	}

	inline void Ln(int N,int *f,int *lnf){
		Inv(N,f,lnf);
		cpy(B,f,N),Der(N,B);
		init_rev(N<<=1);
		NTT(N,lnf,0),NTT(N,B,0);
		for(int i=0;i<N;i++)
			lnf[i]=1ll*lnf[i]*B[i]%mod,B[i]=0;
		NTT(N,lnf,1),N>>=1,clr(lnf+N,N);
		Int(N,lnf);
	}

	inline void Exp(int N,int *f,int *expf){
		expf[0]=1;
		for(int len=2;len<=N;len<<=1){
			cpy(C,expf,len>>1),Ln(len,C,D);
			for(int i=0;i<len;i++)
				if((A[i]=f[i]+mod-D[i])>=mod)A[i]-=mod;
			init_rev(len),NTT(len,A,0),NTT(len,C,0);
			for(int i=0;i<len;i++)
				A[i]=1ll*A[i]*C[i]%mod,C[i]=0;
			NTT(len,A,1),clr(A,len>>1);
			for(int i=len>>1;i<len;i++)
				expf[i]=A[i],A[i]=0;
		}
	}

	template<int MAXN>

	struct Polyn{

		int n,f[MAXN];

		int& operator [](const int x){return f[x];}

		Polyn& operator +=(int b){
			Add(f[0],b);
			return (*this);
		}

		Polyn& operator +=(Polyn &b){
			while(n<b.n)f[n++]=0;
			for(int i=0;i<b.n;i++)Add(f[i],b[i]);
			return (*this);
		}

		Polyn& operator -=(int b){
		    Sub(f[0],b);
			return (*this);
		}

		Polyn& operator -=(Polyn &b){
			while(n<b.n)f[n++]=0;
			for(int i=0;i<b.n;i++)Sub(f[i],b[i]);
			return (*this);
		}

		Polyn& operator *=(long long b){
			for(int i=0;i<n;i++)
				f[i]=f[i]*b%mod;
			return (*this);
		}

		Polyn& operator *=(Polyn &b){
			int N=1;
			for(;N<n+b.n-1;N<<=1);
			init_rev(N);
			for(int i=0;i<b.n;i++)A[i]=b[i];
			NTT(N,f,0),NTT(N,A,0);
			for(int i=0;i<N;i++)
				f[i]=1ll*f[i]*A[i]%mod,A[i]=0;
			NTT(N,f,1),n=n+b.n-1,clr(f+n,N-n);
			return (*this);
		}

		Polyn operator +(int b) const{
			Polyn c(*this);
			return c+=b;
		}

		Polyn operator +(Polyn &b) const{
			Polyn c(*this);
			return c+=b;
		}

		Polyn operator -(int b) const{
			Polyn c(*this);
			return c-=b;
		}

		Polyn operator -(Polyn &b) const{
			Polyn c(*this);
			return c-=b;
		}

		Polyn operator *(long long b) const{
			Polyn c(*this);
			return c*=b;
		}

		Polyn operator *(Polyn &b) const{
			Polyn c(*this);
			return c*=b;
		}

		inline Polyn T(){
			Polyn b(*this);
			std::reverse(b,b+b.n);
			return b;
		}

		inline Polyn Der(){
			Polyn b(*this);
			for(int i=0;i<n-1;i++)
				b[i]=b[i+1]*(i+1ll)%mod;
			b[b.n--]=0;
			return b;
		}

		inline Polyn Int(){
			Polyn b(*this);
			for(int i=b.n;i;i--)
				b[i]=b[i-1]*inv[i]%mod;
			b[0]=0,b.n++;
			return b;
		}

		inline Polyn Inv(int m=0){
			int N=1;
			Polyn b(*this);
			for(m=!m?n:m;N<m;N<<=1);
			Poly::Inv(N,f,b.f),clr(b.f+m,N-m);
			return b;
		}

		inline Polyn Ln(int m=0){
			int N=1;
			Polyn b(*this);
			for(m=!m?n:m;N<m;N<<=1);
			Poly::Ln(N,f,b.f),clr(b.f+m,N-m);
			return b;
		}

		inline Polyn Exp(int m=0){
			int N=1;
			Polyn b(*this);
			for(m=!m?n:m;N<m;N<<=1);
			Poly::Exp(N,f,b.f),clr(b.f+m,N-m);
			return b;
		}

	};

}

Poly::Polyn<maxn> f,g;

int main(){
	f.n=read<int>()+1;
	g.n=read<int>()+1;
	Poly::init(f.n+g.n-1);
	for(int i=0;i<f.n;i++)
		f[i]=read<int>();
	for(int i=0;i<g.n;i++)
		g[i]=read<int>();
	f*=g;
	for(int i=0;i<f.n;i++)
		printf("%d ",f[i]);
	return 0;
}

  

 

贴个老板子

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
 
};

 

posted @ 2021-11-15 19:16  一叶知秋‘  阅读(119)  评论(0编辑  收藏  举报