Loading

多项式全家桶(更新中)

前置

ll rev[N],h[N],intf[N],invf[N],lng[N];
ll qp(ll x,ll y){
	ll ans=1;
	while(y){
		if(y&1)ans=(ans*x)%mod;
		x=(x*x)%mod;y>>=1;
	}
	return ans;
}
void get_rev(ll len){
	for(ll i=0;i<len;i++)rev[i]=(rev[i>>1]>>1)+(i&1?len>>1:0);
}

FFT

double pi=acos(-1.0);
struct comp {
	double a,b;
	comp operator + (const comp &x) const {return {a+x.a,b+x.b};}
	comp operator - (const comp &x) const {return {a-x.a,b-x.b};}
	comp operator * (const comp &x) const {return {a*x.a-b*x.b,a*x.b+b*x.a};}
};
void FFT(int L,comp *f,bool type){
	for(int i=1;i<L;i++){
		r[i]=(r[i>>1]>>1)+((i&1)?L>>1:0);
		if(i<r[i]) swap(f[i],f[r[i]]);
	}
	for(int d=1;d<L;d<<=1){
		comp wd={(cos(pi/d)),(sin(pi/d))};
		if(!type) wd.b=-wd.b;
		w[0]={1,0};
		for(int j=1;j<d;j++) w[j]=w[j-1]*wd;
		for(int i=0;i<L;i+=(d<<1)){
			for(int j=0;j<d;j++){
				comp x=f[i|j],y=w[j]*f[i|j|d];
				f[i|j]=x+y;f[i|j|d]=x-y;
			}
		}
	}
	if(!type) for(int i=0;i<L;i++) f[i].a/=L;
}

NTT

#define mod 998244353
#define G 3
void NTT(ll *f,ll opt,ll L){
	for(ll i=0;i<L;i++)if(i<rev[i])swap(f[i],f[rev[i]]);
	for(ll len=2,mid=1;len<=L;len<<=1,mid<<=1){
		ll wd=qp(G,(mod-1)/len);
		if(!opt)wd=qp(wd,mod-2);
		for(ll l=0;l<L;l+=len){
			for(ll k=l,w=1;k<l+mid;k++,w=(w*wd)%mod){
				ll x=f[k],y=(f[k+mid]*w)%mod;
				f[k]=(x+y)%mod;f[k+mid]=(x-y+mod)%mod;
			}
		}
	}
	if(opt)return;ll w=qp(L,mod-2);
	for(ll i=0;i<L;i++)f[i]=(f[i]*w)%mod;
}

求逆

void INV(ll n,ll *a,ll *b){
	if(n==1){b[0]=qp(a[0],mod-2);return;}
	INV((n+1)>>1,a,b);
	ll len=1;
	while(len<(n<<1)) len<<=1;
	for(ll i=1;i<len;i++) rev[i]=(rev[i>>1]>>1)+(i&1?(len>>1):0);
	for(ll i=0;i<n;i++) c[i]=a[i];for(ll i=n;i<len;i++) c[i]=0;
	NTT(c,len,1);NTT(b,len,1);
	for(ll i=0;i<len;i++) b[i]=(((2-((b[i]*c[i])%mod)+mod)%mod)*b[i])%mod;
	NTT(b,len,0);for(ll i=n;i<len;i++) b[i]=0;
	return;
}

ln

void D(ll n,ll *f){
	for(ll i=0;i<n-1;i++)f[i]=(f[i+1]*(i+1))%mod;f[n-1]=0;
}
void INTE(ll n,ll *f){
	for(ll i=n;i>=1;i--)f[i]=(f[i-1]*qp(i,mod-2))%mod;f[0]=0;
}
void LN(ll *f,ll *g,ll n){
	INV(n,f,invf);for(ll i=0;i<n;i++)intf[i]=f[i];D(n,intf);
	ll L=1;while(L<(n<<1))L<<=1;get_rev(L);
	NTT(intf,1,L);NTT(invf,1,L);
	for(ll i=0;i<L;i++)g[i]=(invf[i]*intf[i])%mod;
	NTT(g,0,L);INTE(n,g);
	for(int i=0;i<L;i++)intf[i]=invf[i]=0;
}

exp

void EXP(ll *f,ll *g,ll n){
	if(n==1){g[0]=1;return;}
	EXP(f,g,(n+1)>>1);
	for(int i=0;i<n;i++)lng[i]=0;
	LN(g,lng,n);
	ll L=1;while(L<(n<<1))L<<=1;get_rev(L);
	for(ll i=0;i<n;i++)lng[i]=(-lng[i]+f[i]+mod)%mod;
	for(ll i=n;i<L;i++)lng[i]=0;lng[0]=(lng[0]+1+mod)%mod;
	NTT(g,1,L);NTT(lng,1,L);
	for(ll i=0;i<L;i++)g[i]=(g[i]*lng[i])%mod;
	NTT(g,0,L);for(ll i=n;i<L;i++)g[i]=0;
}
posted @ 2023-03-25 23:09  eastcloud  阅读(37)  评论(0)    收藏  举报