其他分享
首页 > 其他分享> > 多项式板子

多项式板子

作者:互联网

自己手摸的一套多项式板子,似乎常数并不是很优秀,优化中
默认模数P为998244353

	namespace Poly{
	void FWT_or(int *a,int len,int Ty){
		for(int w=1;w<len;w<<=1)
			for(int j=0;j<len;j+=w*2)
				rep(i,0,w-1)a[i+j+w]+=a[i+j]*Ty;
	}
	void FWT_and(int *a,int len,int Ty){
		for(int w=1;w<len;w<<=1)
			for(int j=0;j<len;j+=w*2)
				rep(i,0,w-1)a[i+j]+=a[i+j+w]*Ty;
	}
	void FWT_xor(int *a,int len,int Ty){
		for(int w=1;w<len;w<<=1)
			for(int j=0;j<len;j+=w*2)
				rep(i,0,w-1){
					int t=a[i+j+w];
					a[i+j+w]=a[i+j]-t;
					a[i+j]+=t;
				}
		if(Ty==-1)rep(i,0,len-1)a[i]/=len;
	}	
	const double pi=acos(-1);
	struct Com{
		double x,y;
		Com operator +(Com &_)const{
			return (Com){x+_.x,y+_.y};
		}
		Com operator -(Com &_)const{
			return (Com){x-_.x,y-_.y};
		}
		Com operator *(Com &_)const{
			return (Com){x*_.x-y*_.y,x*_.y+_.x*y};
		}
	};
	const int M=4e5+10;
	int rev[M];
	void FFT(Com *a,int len,int Ty){
		rep(i,0,len-1)if(i<rev[i])swap(a[i],a[rev[i]]);	
		for(int w=1;w<len;w<<=1){
			Com h={cos(pi/w),sin(pi/w)};
			for(int j=0;j<len;j+=w*2){
				Com g={1,0};
				rep(i,0,w-1){
					Com t=a[i+j+w]*g;
					a[i+j+w]=a[i+j]-t;
					a[i+j]=a[i+j]+t;
					g=g*h;
				}
			}
		}
		if(!Ty){
			reverse(a+1,a+len);
			rep(i,0,len-1)a[i].x/=len;
		}
	}
	void NTT(int *a,int len,int Ty){
		rep(i,0,len-1)if(i<rev[i])swap(a[i],a[rev[i]]);
		for(int w=1;w<len;w<<=1){
			int h=Pow(3,(P-1)/w/2);
			for(int j=0;j<len;j+=w*2){
				int g=1;
				rep(i,0,w-1){
					int t=1ll*a[i+j+w]*g%P;
					a[i+j+w]=a[i+j]-t;
					Mod(a[i+j+w]);
					a[i+j]=a[i+j]+t;
					Mod(a[i+j]);
					g=1ll*g*h%P;
				}
			}
		}
		if(Ty==-1){
			reverse(a+1,a+len);
			int inv=Pow(len,P-2);
			rep(i,0,len-1)a[i]=1ll*a[i]*inv%P;
		}
	}
	int I[M],T[M],D[M],E[M],L[M],S[M];
	void WorkForInv(int *a,int *b,int la){
		if(la==1)return b[0]=Pow(a[0],P-2),void();
		WorkForInv(a,b,(la+1)>>1);
		int len=1;
		while(len<=la+la)len<<=1;
		rep(i,0,len-1)rev[i]=rev[i>>1]>>1|((i&1)*len/2);
		rep(i,0,la-1)T[i]=a[i];
		NTT(T,len,1),NTT(b,len,1);
		rep(i,0,len-1)b[i]=(2ll*b[i]-1ll*b[i]*b[i]%P*T[i]%P+P)%P;
		NTT(b,len,-1);
		rep(i,0,len-1)T[i]=0;
		rep(i,la,len-1)b[i]=0;
	}
	void inv(int *a,int la){WorkForInv(a,I,la);}
	void GetDer(int *a,int *b,int la){
		rep(i,1,la-1)b[i-1]=1ll*a[i]*i%P;
		b[la-1]=0;
	}
	void GetInt(int *a,int *b,int la){
		drep(i,la-2,0)b[i+1]=1ll*a[i]*Pow(i+1,P-2)%P;
		b[0]=0;
	}
	void ln(int *a,int la){
		inv(a,la),GetDer(a,D,la);
		int len=1;
		while(len<=la+la)len<<=1;
		rep(i,0,len-1)rev[i]=rev[i>>1]>>1|((i&1)*len/2);
		NTT(D,len,1),NTT(I,len,1);
		rep(i,0,len-1)T[i]=1ll*D[i]*I[i]%P;
		NTT(T,len,-1),GetInt(T,L,len);
		rep(i,0,len-1)T[i]=I[i]=D[i]=0;
		rep(i,la,len)L[i]=0;
	}
	void WorkForExp(int *a,int *b,int la){
		if(la==1)return b[0]=1,void();
		WorkForExp(a,b,(la+1)>>1);
		int len=1;
		while(len<=la+la)len<<=1;
		rep(i,0,len-1)rev[i]=rev[i>>1]>>1|((i&1)*len/2);
		ln(b,la),GetDer(b,D,la);
		rep(i,0,la-1)T[i]=a[i];
		NTT(T,len,1),NTT(b,len,1),NTT(L,len,1);
		rep(i,0,len-1)b[i]=1ll*b[i]*(P+1-L[i]+T[i])%P;
		NTT(b,len,-1);
		rep(i,0,len-1)T[i]=L[i]=D[i]=0;
		rep(i,la,len-1)b[i]=0;
	}
	void exp(int *a,int la){WorkForExp(a,E,la);}
	int inv2=Pow(2,P-2);
	void WorkForSqrt(int *a,int *b,int la){
		if(la==1)return b[0]=1,void();
		WorkForSqrt(a,b,(la+1)>>1);
		int len=1;
		while(len<=la+la)len<<=1;
		rep(i,0,len-1)rev[i]=rev[i>>1]>>1|((i&1)*len/2);
		inv(b,la);
		rep(i,0,la-1)T[i]=a[i];
		NTT(I,len,1),NTT(T,len,1);
		rep(i,0,len-1)T[i]=1ll*T[i]*I[i]%P;
		NTT(T,len,-1);
		rep(i,0,la-1)b[i]=1ll*(b[i]+T[i])*inv2%P;
		rep(i,0,len-1)T[i]=I[i]=0;
	}
	void sqrt(int *a,int la){WorkForSqrt(a,S,la);}
}

恶心坏我了,呕~~~

标签:la,int,多项式,rep,NTT,len,板子,void
来源: https://www.cnblogs.com/Saltywater/p/15086695.html