多 项 式 全 家 桶


恶心人的多项式。

C风格(较快)

#include
#define clr(f,len) memset(f,0,(len)<<2)
#define cpy(f,g,len) memcpy(f,g,(len)<<2)
#define IMP(lim,anw) for(i=0;i^(lim);++i)anw
typedef unsigned ui;
const ui M=5e5+5,mod=998244353;
ui lim,inv[M],buf[M<<2];
ui *now=buf,*w[23];
inline void swap(ui&a,ui&b){
    ui c=a;a=b;b=c;
}
inline ui Add(const ui&a,const ui&b){
    return a+b>=mod?a+b-mod:a+b;
}
inline ui Del(const ui&a,const ui&b){
    return b>a?a-b+mod:a-b;
}
inline void px(ui*f,ui*g,const ui&len){
    for(ui i=0;i^len;++i)f[i]=1ull*f[i]*g[i]%mod;
}
inline void reverse(ui*f,int len){
    for(ui i=0;(i<<1|1)>=1,a=1ull*a*a%mod)if(b&1)ans=1ull*ans*a%mod;
    return ans;
}
inline ui Getlen(const ui&n){
    ui len=0;
    while((1<>1)/n);
    for(i=2;i<(1<=1;--j){
        w[j]=now;now+=1<>1,d=M;len^0;len>>=1,--d){
        W=w[d];
        for(k=0;k^n;k+=len<<1){
            fl=f+(k);fr=f+(k|len);
            IMP(len,(x=fl[i],y=fr[i])),fl[i]=Add(x,y),fr[i]=1ull*Del(x,y)*W[i]%mod;
        }
    }
}
inline void IDFT(ui*f,const ui&n,const ui&M){
    ui i,k,d,x,y,*W,*fl,*fr,len;
    for(len=1,d=1;len^n;len<<=1,++d){
        W=w[d];
        for(k=0;k^n;k+=len<<1){
            fl=f+(k);fr=f+(k|len);
            IMP(len,(x=fl[i],y=1ull*fr[i]*W[i]%mod)),fl[i]=Add(x,y),fr[i]=Del(x,y);
        }
    }
    k=pow(n);IMP(n,f[i]=1ull*f[i]*k%mod);
    for(i=1;(i<<1)

使用 vector 封装(较慢)

#include
#include
#include
#include
#define IMP(lim,anw) for(i=0;i^(lim);++i)anw
typedef unsigned ui;
const ui M=5e6+5,mod=998244353;
ui lim,Inv[M],buf[M<<2];ui*now=buf,*w[23];
inline void swap(ui&a,ui&b){
	ui c=a;a=b;b=c;
}
inline ui Add(const ui&a,const ui&b){
	return a+b>=mod?a+b-mod:a+b;
}
inline ui Del(const ui&a,const ui&b){
	return b>a?a-b+mod:a-b;
}
inline ui max(const ui&a,const ui&b){
	return a>b?a:b;
}
inline void write(ui n){
	static char s[10];ui top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top--]),top);
}
inline ui read(){
	ui n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline ui pow(ui a,ui b=mod-2){
	ui ans=1;
	for(;b;b>>=1,a=1ull*a*a%mod)if(b&1)ans=1ull*ans*a%mod;
	return ans;
}
inline ui Getlen(const ui&n){
	ui len=0;
	while((1<>1)/n);
	for(i=2;i<(1<=1;--j){
		w[j]=now;now+=1<F;
	Poly(const Poly&G){F=G.F;}
	Poly(const std::vectorG){F=G;}
	Poly(const ui&x=0){if(x)F=std::vector(x);}
	inline Poly&resize(const ui&len){
		F.resize(len);return*this;
	}
	inline ui size()const{
		return F.size();
	}
	inline ui&operator[](const ui&id){
		return F[id];
	}
	inline void push_back(const ui&x){
		F.push_back(x);
	}
	inline Poly&reverse(){
		std::reverse(F.begin(),F.end());return*this;
	}
	inline Poly operator>>(const ui&x){
		ui i;Poly G;IMP(F.size()-x,G.push_back(F[i+x]));return G;
	}
	inline Poly operator<<(const ui&x){
		ui i;Poly G;G.resize(x);IMP(F.size(),G.push_back(F[i]));return G;
	}
	inline void px(Poly G){
		F.resize(max(F.size(),G.size()));G.resize(F.size());
		for(ui i(0);i^F.size();++i)F[i]=1ull*F[i]*G[i]%mod;
	}
	inline Poly&Der(){
		for(ui i(1);i^F.size();++i)F[i-1]=1ull*F[i]*i%mod;F.pop_back();
		return*this;
	}
	inline Poly&Int(){
		F.push_back(0);
		for(ui i(F.size()-1);i;--i)F[i]=1ull*F[i-1]*::Inv[i]%mod;F[0]=0;
		return*this;
	}
	inline void DFT(const ui&M){
		ui i,k,d,x,y,len,*W;F.resize(1<>1,d=M;len;len>>=1,--d){
			W=w[d];
			for(k=0;k^F.size();k+=len<<1){
				IMP(len,(x=F[i|k],y=F[i|k|len])),F[i|k]=Add(x,y),F[i|k|len]=1ull*Del(x,y)*W[i]%mod;
			}
		}
	}
	inline void IDFT(const ui&M){
		ui i,k,d,x,y,len,*W;F.resize(1<F;ui i;F.resize(max(F.size(),G.size()));G.resize(F.size());
		IMP(F.size(),F[i]=Add(F[i],G[i]));return F;
	}
	inline Poly operator-(Poly G)const{
		Poly F=this->F;ui i;F.resize(max(F.size(),G.size()));G.resize(F.size());
		IMP(F.size(),F[i]=Del(F[i],G[i]));return F;
	}
	inline Poly operator*(const ui&x)const{
		Poly F=this->F;ui i;
		IMP(F.size(),F[i]=1ull*F[i]*x%mod);return F;
	}
	inline Poly operator*(Poly G)const{
		Poly F=*this;const ui&len=F.size()+G.size()-1,M=Getlen(len);
		G.resize(1<>=(const ui&x){
		return*this=operator>>(x);
	}
	inline Poly&operator<<=(const ui&x){
		return*this=operator<<(x);
	}
	inline Poly&operator+=(const Poly&G){
		return*this=*this+G;
	}
	inline Poly&operator-=(const Poly&G){
		return*this=*this-G;
	}
	inline Poly&operator*=(const Poly&G){
		return*this=*this*G;
	}
	inline Poly&operator/=(const Poly&G){
		return*this=*this/G;
	}
	inline Poly&operator%=(const Poly&G){
		return*this=*this%G;
	}
	inline Poly&inv(){
		Poly b1,b2,b3;if(!F.empty())b1.push_back(::pow(F[0]));
		ui i,M=Getlen(F.size()),len;
		for(len=1;len<=M;++len){
			b3=b1*2;(b2=F).resize(1<Der()*=G.inv()).resize(len)).Int();
	}
	inline Poly&exp(){
		Poly b1,b2;ui i,M=Getlen(F.size()),len;b1.push_back(1);
		for(len=1;len<=M;++len){
			b2=b1;b2.resize(1<ln();IMP(F.size(),F[i]=1ull*F[i]*k%mod);return this->exp();
	}
};
inline Poly resize(Poly F,const ui&n){
	return F.resize(n);
}
inline Poly reverse(Poly F){
	return F.reverse();
}
inline Poly Int(Poly F){
	return F.Int();
}
inline Poly Der(Poly F){
	return F.Der();
}
inline Poly px(Poly F,Poly G){
	return F.px(G),F;
}
inline Poly inv(Poly F){
	return F.inv();
}
inline Poly ln(Poly F){
	return F.ln();
}
inline Poly exp(Poly F){
	return F.exp();
}
inline Poly sqrt(Poly F){
	return F.sqrt();
}
inline Poly pow(Poly F,const ui&k){
	return F.pow(k);
}