Hello, World:写在这个博客的开头

注册了个博客园玩玩,还是要学一学怎么用……

虽然但是,感觉自己学 OI 的时间也不会很长了,最近已经做好了 NOIP 后就退役的准备。

不太清楚在最后一个多月的时间里开一个博客到底有没有意义,嘛估计我以后也懒得往这里写点什么就是了……

不知道后面应该写点啥了,放个最朴素的不完善多项式板子吧

/*
已经包含的内容:
- 乘法
- 求导 / 积分
- 求逆
- 指数 / 对数
- 除法 / 取模
- 开根
--------------------------
还不会写的内容:
- 求幂 (板子题数据范围离谱,我鸽了)
- 多点求值
- 快速插值
- ...
- To Be Continued
*/
#include<cstdio>
const int N=1000086,MOD=998244353,g=3,gi=332748118;
int fac[N],iv[N],inv[N];
int Max(int a,int b){return a>b?a:b;}
int Min(int a,int b){return a<b?a:b;}
bool Swap(int &a,int &b){a+=b;b=a-b;a-=b;return true;}
int read(){
	char ch=getchar();int nn=0,ssss=1;
	while(ch<'0'||ch>'9'){if(ch=='-')ssss*=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){nn=nn*10+(ch-'0');ch=getchar();}
	return nn*ssss;
}
int qpow(int a,int b){
	int ret=1;
	while(b){if(b&1)ret=1ll*ret*a%MOD;a=1ll*a*a%MOD;b>>=1;}
	return ret;
}
namespace PolyCalc{
	int rev[N],tm[N],ti[N],tl[N],te[N],td[N],ts[N],lim;
	bool getrev(int nl){//位逆序置换预处理
		lim=1;int len=0;while(lim<=nl)lim<<=1,len++;
		for(int i=0;i<lim;i++)rev[i]=rev[i>>1]>>1|((i&1)<<(len-1));
		return true;
	}
	bool Rev(int a[],int len){for(int i=0;i<len-i;i++)Swap(a[i],a[len-i]);return true;}
	bool NTT(int a[],int p){
		for(int i=0;i<lim;i++)if(i<rev[i])Swap(a[i],a[rev[i]]);
		for(int mid=1;mid<lim;mid<<=1){
			int wn=qpow(p>0?g:gi,(MOD-1)/(mid<<1));
			for(int j=0;j<lim;j+=(mid<<1)){
				int w=1;
				for(int k=0;k<mid;k++,w=1ll*w*wn%MOD){
					int x=a[j+k],y=1ll*w*a[j+mid+k]%MOD;
					a[j+k]=(x+y)%MOD;a[j+mid+k]=(x-y+MOD)%MOD;
				}
			}
		}
		if(p>0)return true;
		int invn=qpow(lim,MOD-2);
		for(int i=0;i<lim;i++)a[i]=1ll*a[i]*invn%MOD;
		return true;
	}
	bool Add(int a[],int b[],int c[],int len){for(int i=0;i<=len;i++)c[i]=(a[i]+b[i])%MOD;return true;}
	int Sub(int a[],int b[],int c[],int len){
		int mp=0;for(int i=0;i<=len;i++)c[i]=(a[i]-b[i]+MOD)%MOD,mp=Max(mp,i*(c[i]!=0));
		return mp;
	}
	bool Mul(int a[],int b[],int c[],int n,int m){//乘法
		getrev(n+m);for(int i=0;i<lim;i++)tm[i]=a[i]*(i<=n),c[i]=b[i]*(i<=m);
		NTT(tm,1);NTT(c,1);
		for(int i=0;i<lim;i++)c[i]=1ll*c[i]*tm[i]%MOD;
		NTT(c,-1);return true;
	}
	bool D(int a[],int b[],int len){//求导
		for(int i=0;i<len;i++)b[i]=1ll*a[i+1]*(i+1)%MOD;b[len]=0;
		return true;
	}
	bool S(int a[],int b[],int len){//积分
		b[0]=0;for(int i=0;i<len;i++)b[i+1]=1ll*a[i]*inv[i+1]%MOD;
		return true;
	}
	bool getinv(int a[],int b[],int len){//乘法逆
		if(len==1){b[0]=qpow(a[0],MOD-2);return true;}
		getinv(a,b,(len+1)>>1);getrev((len-1)<<1);
		for(int i=0;i<lim;i++)ti[i]=a[i]*(i<len),b[i]=b[i]*(i<len);
		NTT(ti,1);NTT(b,1);
		for(int i=0;i<lim;i++)b[i]=1ll*(2-1ll*ti[i]*b[i]%MOD+MOD)*b[i]%MOD;
		NTT(b,-1);for(int i=len;i<lim;i++)b[i]=0;return true;
	}
	bool getln(int a[],int b[],int len){//对数
		D(a,b,len-1);getinv(a,tl,len);Mul(b,tl,tl,len-1,len-1);S(tl,b,len-1);
		for(int i=0;i<lim;i++)tl[i]=0;return true;
	}
	bool getexp(int a[],int b[],int len){//指数
		if(len==1){b[0]=1;return true;}
		getexp(a,b,(len+1)>>1);getln(b,te,len);getrev((len-1)<<1);
		for(int i=0;i<len;i++)te[i]=(a[i]+(i==0)-te[i]+MOD)%MOD;
		Mul(te,b,b,len-1,len-1);for(int i=len;i<lim;i++)b[i]=te[i]=0;
		return true;
	}
	int Div(int a[],int b[],int f[],int g[],int n,int m){//带余除法
		for(int i=0;i<=n;i++)td[i]=0;
		Rev(a,n);Rev(b,m);getinv(b,td,n-m+1);
		Mul(a,td,f,n-m,n-m);for(int i=n-m+1;i<lim;i++)f[i]=0;
		Rev(f,n-m);Rev(a,n);Rev(b,m);Mul(b,f,td,m,n-m);
		return Sub(a,td,g,n);
	}
	bool getsqrt(int a[],int b[],int len){//开根
		if(len==1){b[0]=1;return true;}
		int iv=499122177,ll=(len+1)>>1;
		getsqrt(a,b,(len+1)>>1);getinv(b,ts,len);
		Mul(b,b,b,ll-1,ll-1);Add(a,b,b,len);Mul(b,ts,b,len-1,len-1);
		for(int i=0;i<len;i++)b[i]=1ll*b[i]*iv%MOD,ts[i]=0;
		for(int i=len;i<lim;i++)b[i]=ts[i]=0;
		return true;
	}
}
struct Poly{
	int len,a[N];
	Poly(){len=0;}
	Poly(int x){len=x;}
	bool getin(){
		len=read()-1;for(int i=0;i<=len;i++)a[i]=read();
		return true;
	}
	int& operator [](int x){return a[x];}
	Poly operator *(Poly b){
		Poly ret=Poly(len+b.len);PolyCalc::Mul(a,b.a,ret.a,len,b.len);return ret;
	}
	Poly operator /(Poly b){
		Poly d=Poly(len-b.len),dm=Poly(len);
		dm.len=PolyCalc::Div(a,b.a,d.a,dm.a,len,b.len);return d;
	}
	Poly operator %(Poly b){
		Poly d=Poly(len-b.len),dm=Poly(len);
		dm.len=PolyCalc::Div(a,b.a,d.a,dm.a,len,b.len);return dm;
	}
	Poly Sqrt(){Poly ret=Poly(len);PolyCalc::getsqrt(a,ret.a,len+1);return ret;}
	Poly Inv(){Poly ret=Poly(len);PolyCalc::getinv(a,ret.a,len+1);return ret;}
	Poly Exp(){Poly ret=Poly(len);PolyCalc::getexp(a,ret.a,len+1);return ret;}
	Poly Ln(){Poly ret=Poly(len);PolyCalc::getln(a,ret.a,len+1);return ret;}
}a;
int main(){
	a.getin();
	inv[1]=1;for(int i=2;i<=a.len;i++)inv[i]=1ll*(MOD-MOD/i)*inv[MOD%i]%MOD;
	fac[0]=iv[0]=1;
	for(int i=1;i<=a.len;i++)fac[i]=1ll*fac[i-1]*i%MOD;
	iv[a.len]=qpow(fac[a.len],MOD-2);for(int i=a.len-1;i;i--)iv[i]=1ll*iv[i+1]*(i+1)%MOD;
}
posted @ 2021-10-05 15:45  LFCode  阅读(99)  评论(3编辑  收藏  举报