简单封装Poly

非常优雅的马蜂

#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define cp complex<double>
#define fir first
#define sec second
using namespace std;

const int maxn=4e6+10,Mod=998244353;

int pw(int x,int p){int res=1,base=x;while(p){if(p&1)res=1LL*res*base%Mod;base=1LL*base*base%Mod;p>>=1;}return res;}
int Inv(int x){return pw(x,Mod-2);}

int W[maxn],Cw[maxn],rev[maxn];
int deg,lg;
void Init(int len){
	deg=1,lg=0;while(deg<len)deg<<=1,++lg;
	W[0]=Cw[0]=1;int Wp=pw(3,(Mod-1)/deg),Cp=pw(Inv(3),(Mod-1)/deg);
	for(int i=1;i<deg;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1)),W[i]=1LL*W[i-1]*Wp%Mod,Cw[i]=1LL*Cw[i-1]*Cp%Mod;
}

struct Poly{	
	vector<int>f;
	int &operator[](const int &i){return f[i];}
	int operator[](const int &i)const{return f[i];}
	int Deg(){return f.size();}
	int Deg()const{return f.size();}
	void Set(int len){f.resize(len);}
	void Adjust(){while(f.size()>1 && f.back()==0)f.pop_back();}
	void Reverse(){reverse(f.begin(),f.end());}
	void Print(){for(auto it : f)cerr<<it<<" ";cerr<<"\n";}
	void Diri(){for(int i=0;i+1<(int)f.size();++i)f[i]=1LL*f[i+1]*(i+1)%Mod;f.back()=0;}
	void Integ(){for(int i=((int)f.size())-1;i>=1;--i)f[i]=1LL*f[i-1]*::Inv(i)%Mod;f[0]=0;}
	Poly Dir(){Poly res;res.Set(Deg());for(int i=0;i+1<f.size();++i)res[i]=1LL*f[i+1]*(i+1)%Mod;return res;}
	Poly Inte(){Poly res;res.Set(Deg());for(int i=((int)f.size()-1);i>=1;--i)res[i]=1LL*f[i-1]*::Inv(i)%Mod;return res;}
	void NTT(int deg,int w[],int opt){
		Set(deg);for(int i=0;i<deg;++i)if(i<rev[i])swap(f[i],f[rev[i]]);
		for(int t=deg>>1,m=1;m<deg;m<<=1,t>>=1)for(int i=0;i<deg;i+=(m<<1))for(int j=0;j<m;++j)
		{ int x=f[i+j],y=1LL*w[t*j]*f[i+j+m]%Mod;f[i+j]=(x+y)%Mod,f[i+j+m]=(x-y+Mod)%Mod;}
		if(opt==-1){int inv=::Inv(deg);for(int i=0;i<deg;++i)f[i]=1LL*f[i]*inv%Mod;}
	}
	friend Poly operator + (const Poly &x,const Poly &y){
		Poly res; res.Set(max(x.Deg(),y.Deg()));
		for(int i=0;i<x.Deg();++i)res[i]=x[i];
		for(int i=0;i<y.Deg();++i)res[i]=(res[i]+y[i])%Mod;
		return res;
	}
	void operator += (const Poly &x){
		Set(max(Deg(),x.Deg()));
		for(int i=0;i<x.Deg();++i)f[i]=(f[i]+x[i])%Mod;
	}
	friend Poly operator - (const Poly &x,const Poly &y){
		Poly res; res.Set(max(x.Deg(),y.Deg()));
		for(int i=0;i<x.Deg();++i)res[i]=x[i];
		for(int i=0;i<y.Deg();++i)res[i]=(res[i]-y[i]+Mod)%Mod;
		return res;
	}
	void operator -= (const Poly &x){
		Set(max(Deg(),x.Deg()));
		for(int i=0;i<x.Deg();++i)f[i]=(f[i]-x[i]+Mod)%Mod;
	}
	friend Poly operator * (const Poly &x,const Poly &y){
		Poly res,A=x,B=y;
		Init(A.Deg()+B.Deg()-1);
		A.NTT(deg,W,1);B.NTT(deg,W,1);res.Set(deg);
		for(int i=0;i<deg;++i)res[i]=1LL*A[i]*B[i]%Mod;
		res.NTT(deg,Cw,-1);res.Adjust();
		return res;
	}
	void operator *= (const Poly &x){
		Poly A=x;
		Init(Deg()+A.Deg()-1);
		NTT(deg,W,1),A.NTT(deg,W,1);
		for(int i=0;i<deg;++i)f[i]=1LL*f[i]*A[i]%Mod;
		NTT(deg,Cw,-1);Adjust();
	}
	friend Poly operator / (const Poly &x,const Poly &y){
		Poly E=x,D=y;
		E.Reverse(),D.Reverse();D.Set(x.Deg()-y.Deg()+1);
		D=D.Inv();D*=E;
		D.Set(x.Deg()-y.Deg()+1); D.Reverse();
		return D;
	}
	friend pair<Poly,Poly> operator % (const Poly &x,const Poly &y){
		Poly E=x,D=y;
		E.Reverse(),D.Reverse();D.Set(x.Deg()-y.Deg()+1);
		D=D.Inv();D*=E;
		D.Set(x.Deg()-y.Deg()+1); D.Reverse();
		Poly R=x-D*y; R.Set(x.Deg()-1);
		return {D,R};
	}
	Poly Inv(){
		Poly res;res.Set(1);
		if(f.empty())return res;
		int len,lim;res[0]=::Inv(f[0]);Poly A,B;
		for(len=2;len<(Deg()<<1);len<<=1){
			A.f.assign((*this).f.begin(),(*this).f.begin()+min(len,Deg())),B=res;
			B.Set(min(len,Deg()));
			Init(A.Deg()+B.Deg()-1);A.NTT(deg,W,1),B.NTT(deg,W,1);res.Set(deg);
			for(int i=0;i<deg;++i)res[i]=((2LL-1LL*A[i]*B[i]%Mod)*B[i]%Mod+Mod)%Mod;
			res.NTT(deg,Cw,-1);
			res.Set(len);
		}
		res.Set(Deg());return res;
	}
	Poly Ln(){
		Poly res=Dir();Poly I=Inv();
		res*=I;res.Integ(); res.Set(Deg());
		return res;
	}
	Poly Exp(){
		Poly res;res.Set(1);res[0]=1;
		int len;Poly A,B;
		for(len=2;len<(Deg()<<1);len<<=1){
			res.Set(len);A=res.Ln();
			B.f.assign((*this).f.begin(),(*this).f.begin()+min(len,Deg()));
			B-=A;B[0]++;res*=B;
			res.Set(len);
		}
		res.Set(Deg());return res;
	}
	Poly Pow(int k){
		Poly res=Ln();
		for(int i=0;i<res.Deg();++i)res[i]=1LL*res[i]*k%Mod;
		return res.Exp();
	}
	Poly Sqrt(){
		Poly res;res.Set(1);res[0]=1;
		int len;Poly A,B;int inv2=::Inv(2);
		for(len=2;len<(Deg()<<1);len<<=1){
			res.Set(len);A=res.Inv();
			B.f.assign((*this).f.begin(),(*this).f.begin()+min(len,Deg()));
			A*=B;
			for(int i=0;i<len;++i)res[i]=1LL*(res[i]+A[i])*inv2%Mod;
			res.Set(len);
		}
		res.Set(Deg());return res;
	}
}F,G;
int n,m;

void solve(){ }
int main (){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }
posted @ 2023-01-04 16:49  Delov  阅读(192)  评论(2编辑  收藏  举报