欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[第一类斯特林求行]

程序员文章站 2023-12-27 12:37:39
...

[第一类斯特林求行]


如题,复杂度一个log

  • 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353,g=3;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
const int N=5e5+5;
int rev[N],fac[N],ifac[N];

inline void init(int n){
	fac[0]=ifac[0]=1;for(int i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
	ifac[n]=qpow(fac[n],mod-2);for(int i=n-1;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
int comb(int a,int b){if(b>a)return 0;return mul(fac[a],mul(ifac[b],ifac[a-b]));}
/*math&comb*/
typedef vector<int> Poly;
void DFT(int *t,int n,int type){
	int l=0;while(1<<l<n)++l;
	for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
	for(int i=0;i<n;i++)if(rev[i]>i)swap(t[rev[i]],t[i]);
	for(int step=1;step<n;step<<=1){
		int wn=qpow(g,(mod-1)/(step<<1));
		for(int i=0;i<n;i+=step<<1){
			int w=1;
			for(int k=0;k<step;k++,w=mul(w,wn)){
				int x=t[i+k],y=mul(t[i+k+step],w);
				t[i+k]=add(x,y),t[i+k+step]=sub(x,y);
			}
		}
	}
	if(type==1)return;
	for(int i=1;i<n-i;i++)swap(t[i],t[n-i]);
	int inv=qpow(n,mod-2);
	for(int i=0;i<n;i++)t[i]=mul(t[i],inv);
}
Poly NTT(Poly A,int n,Poly B,int m){
	static Poly res,PolA,PolB;
	PolA=A,PolB=B;
	int len=1;while(len < n+m)len<<=1;
	res.resize(len);
	PolA.resize(len),PolB.resize(len);
	DFT(&PolA[0],len,1);DFT(&PolB[0],len,1);
	for(int i=0;i<len;i++) res[i]= mul(PolA[i],PolB[i]);
	DFT(&res[0],len,-1);
	res.resize(n+m-1);
	return res;
}
Poly NTT(Poly A,Poly B){
	return NTT(A,A.size(),B,B.size());
}

Poly Getstirling(int X){
	Poly ret;
	if(X==0){
		ret.resize(1);ret[0]=1;
		return ret;
	}
	if(X==1){
		ret.resize(2);ret[0]=0,ret[1]=1;
		return ret;
	}
	if(X==2){
		ret.resize(3);ret[0]=0,ret[1]=1,ret[2]=1;
	}
	int nn=X/2+1;
	Poly pst=Getstirling(X/2);
	int t=X/2;
	Poly snd=pst,tmp;
	for(int i=0;i<nn;i++) snd[i]=mul(snd[i],fac[i]);
	tmp.resize(nn);
	for(int i=0;i<nn;i++) tmp[i]=mul(qpow(t,nn-1-i),ifac[nn-1-i]);
	Poly R=NTT(snd,tmp);
	snd.resize(nn);
	for(int i=0;i<nn;i++) snd[i]=mul(ifac[i],R[i+nn-1]);
	ret=NTT(pst,snd);
	if(X%2){
		ret.resize(X+1);
		for(int i=X;i;i--){
			ret[i]=add(mul(ret[i],X-1),ret[i-1]);
		}
	}
	return ret;
}
int n,a,b;
Poly S;


int main()
{
	cin>>n>>a>>b;a--,b--;
	if(a<0||b<0){
		puts("0");return 0;
	}
	init(400000);S=Getstirling(n-1);
	int St=0;
	if(a+b<S.size()){
		St=S[a+b];
	}
	St=mul(St,comb(a+b,b));
	printf("%d\n",St);
}

 

上一篇:

下一篇: