多项式全家桶

#define lon long long
#define Dinv(x) Dpow(x,mo-2)	
#define die(x) memset(x,0,sizeof x)

lon Dpow(lon p,lon q){
	lon tot=1;
	while(q){
		if(q&1)tot=tot*p%mo;
		p=p*p%mo,q=q>>1;
	}
	return tot;
}
	
namespace POLY{
	#define init(x) const int p7=(x)+10
	#define bye(s,f,x) rep(i,0,x)s[i]=f[i]
	
	const int q7=n7;
	lon ori1[q7],ori2[q7],rv[q7];
	
	lon Dpow(lon p,lon q){
		lon tot=1;
		while(q){
			if(q&1)tot=tot*p%mo;
			p=p*p%mo,q=q>>1;
		}
		return tot;
	}
	
	void Tpre(int n){
		lon inv=Dinv(3);
		for(int len=2;len<=n+1;len=len<<1){
			ori1[len]=Dpow(3,(mo-1)/len);
			ori2[len]=Dpow(inv,(mo-1)/len);
		}
	}
	
	void Trev(int n){
		rep(i,0,n){
			rv[i]=(rv[i>>1]>>1);
			if(i&1)rv[i]=rv[i]|((n+1)>>1);
		}	
	}
	
	int totwo(int x){
		int z=1;
		while(z<=x)z=z<<1;
		return z;
	}
	
	void NTT(lon *f,int n,bool sys){
		rep(i,0,n){
			if(i<rv[i])swap(f[i],f[ rv[i] ]);
		}
		for(int len=1;len<n+1;len=len<<1){
			int far=len<<1;
			lon ori=sys?ori2[far]:ori1[far];
			for(int i=0;i<=n;i=i+far){
				lon z=1;
				rep(j,i,i+len-1){
					lon tmp=z*f[len+j]%mo;
					f[len+j]=(f[j]-tmp+mo)%mo;
					f[j]=(f[j]+tmp)%mo;
					z=z*ori%mo;
				}
			}
		}
		if(sys){
			lon inv=Dinv(n+1);
			rep(i,0,n)f[i]=f[i]*inv%mo;		
		}
	}
	
	void Tmul(lon *f,lon *g,int n){
		Trev(n);
		NTT(f,n,0),NTT(g,n,0);
		rep(i,0,n)f[i]=f[i]*g[i]%mo;
		NTT(f,n,1);
	}
	
	void Tmulz(lon *f,lon *g,lon *S,int n){
		init(n<<1);lon A[p7],B[p7];
		die(A),die(B);
		rep(i,0,n)A[i]=f[i],B[i]=g[i];
		Trev(n);
		NTT(A,n,0),NTT(B,n,0);
		rep(i,0,n)A[i]=A[i]*B[i]%mo;
		NTT(A,n,1);
		bye(S,A,n);
	}
	
	void Tinv(lon *f,lon *S,int n){
		init(n<<1);lon s[p7],A[p7],B[p7];
		die(A),die(B),die(s);
		s[0]=Dpow(f[0],mo-2);
		for(int len=2;len<=n+1;len=len<<1){
			int far=(len<<1)-1;
			rep(i,0,len-1)A[i]=f[i],B[i]=s[i];
			Trev(far);
			NTT(A,far,0),NTT(B,far,0);
			rep(i,0,far)s[i]=(B[i]*2%mo-A[i]*B[i]%mo*B[i]%mo+mo)%mo;
			NTT(s,far,1);
			rep(i,len,far)s[i]=0;
		}
		bye(S,s,n);
	}
	
	void Tderiv(lon *f,lon *S,int n){
		init(n);lon s[p7];s[n]=0;
		rep(i,1,n)s[i-1]=f[i]*i%mo;
		bye(S,s,n);
	}
	
	void Tint(lon *f,lon *S,int n){
		init(n);lon s[p7];s[0]=0;
		rep(i,0,n-1)s[i+1]=f[i]*Dpow(i+1,mo-2)%mo;
		bye(S,s,n);
	}
	
	void Tln(lon *f,lon *S,int n){
		init(n<<1);lon A[p7],B[p7];
		die(A),die(B);
		rep(i,0,n)A[i]=f[i];
		Tderiv(A,B,n);
		Tinv(A,A,n);
		Tmul(A,B,n+n+1);
		Tint(A,A,n);
		bye(S,A,n);
	}
	
	void Texp(lon *f,lon *S,int n){
		init(n<<1);lon s[p7],A[p7],B[p7],C[p7];
		die(A),die(B),die(C),die(s);
		s[0]=1;
		for(int len=2;len<=n+1;len=len<<1){
			int far=(len<<1)-1;
			rep(i,0,len-1)A[i]=f[i],B[i]=s[i];
			Tln(B,C,len-1);
			rep(i,0,len-1)C[i]=(A[i]-C[i]+mo)%mo;
			C[0]=(C[0]+1)%mo;
			Trev(far);
			NTT(B,far,0),NTT(C,far,0);
			rep(i,0,far)s[i]=B[i]*C[i]%mo;
			NTT(s,far,1);
			rep(i,len,far)s[i]=0;
		}
		bye(S,s,n);
	}
	
	void Tsqrt(lon *f,lon *S,int n){
		init(n<<1);lon s[p7],A[p7],B[p7],C[p7];
		die(A),die(B),die(C),die(s);
		s[0]=1;lon inv=Dinv(2);
		for(int len=1;len<=n+1;len=len<<1){
			int far=(len<<1)-1;
			rep(i,0,len-1)A[i]=f[i],B[i]=s[i];
			Tinv(B,C,len-1);
			Trev(far);
			NTT(A,far,0),NTT(C,far,0);
			rep(i,0,far)s[i]=A[i]*C[i]%mo;
			NTT(s,far,1);
			rep(i,0,len-1)s[i]=(s[i]+B[i])%mo*inv%mo;
			rep(i,len,far)s[i]=0;
		}
		bye(S,s,n);
	}
	
	void Tpow(lon *f,lon *S,int n,lon K){
		init(n<<1);lon s[p7];die(s);
		Tln(f,s,n);
		rep(i,0,n)s[i]=s[i]*K%mo;
		Texp(s,s,n);
		bye(S,s,n);
	}	
	
	void Tturn(lon *f,int n){
		rep(i,0,n/2)swap(f[i],f[n-i]);
	}

	void Tdiv(lon *f,lon *g,lon *S,lon *Syu,int n,int m){
		init((n+m)<<2);lon A[p7],B[p7],s[p7],sz[p7],syu[p7];
		die(A),die(B),die(s),die(sz);
		rep(i,0,n)A[i]=f[i];
		rep(i,0,m)B[i]=g[i];
		Tturn(A,n),Tturn(B,m);
		int z1=totwo(n-m+1)-1;
		Tinv(B,B,z1);
		int z2=totwo(n+n-m+1)-1;
		rep(i,n-m+1,z2)B[i]=0;
		Tmul(A,B,z2);
		rep(i,0,n-m)s[i]=A[i];
		Tturn(s,n-m);
		rep(i,0,n-m)sz[i]=s[i];
		int z3=totwo(n+1)-1;
		rep(i,0,m)B[i]=g[i];
		rep(i,m+1,z3)B[i]=0;	
		Tmul(B,s,z3);
		rep(i,0,m)syu[i]=(f[i]-B[i]+mo)%mo;
		bye(S,sz,n-m);bye(Syu,syu,m);
	}
}
posted @ 2021-03-09 21:46  BlankAo  阅读(46)  评论(0编辑  收藏  举报