P5409 第一类斯特林数·列

套路:\(1\)个的母函数是\(f\),则\(n\)个的母函数是\(f^n\)

设单个圆排列的\(\text{EGF}\)\(f=\sum (i-1)!\frac{x^i}{i!}=\sum \frac{x^i}{i}\),答案即为\(\frac{f^m}{m!}\)(圆排列全同)。

可以这样理解:假设圆排列不同,最后除以\(m!\)即可。

假设第\(i\)个圆排列有\(a_i\)个数(\(\sum a_i=n\)),那么它可以产生\((a_i-1)!\)的贡献。

那么这个情况有\(\frac{n!}{\prod a_i!}\prod (a_i-1)!\),明显是\(\text{EGF}\)相乘的形式。

题解多为\(\text{ln}\)然后\(\text{exp}\),由于我还不会\(\text{exp}\),所以提供一个\(\Theta(n\log^2 n)\)的写法。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int mod=167772161;
const int G=3;
const int iG=(mod+1)/3;
int n,m,len=1,tr[maxn];
int fac[maxn],inv[maxn],ifc[maxn];
inline int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=1ll*res*x%mod;
		x=1ll*x*x%mod;y>>=1;
	}
	return res;
}
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
inline void ntt(int *f,int len,int flag){
	for(int i=0;i<len;++i)
		if(i<tr[i])swap(f[i],f[tr[i]]);
	for(int p=2;p<=len;p<<=1){
		int l=p>>1,w=ksm(flag?G:iG,(mod-1)/p);
		for(int i=0;i<len;i+=p){
			int wi=1;
			for(int j=i;j<i+l;++j){
				int t=1ll*wi*f[j+l]%mod;
				f[j+l]=(f[j]-t+mod)%mod;
				f[j]=(f[j]+t)%mod;
				wi=1ll*w*wi%mod;
			}
		}
	}
	if(!flag){
		int iv=ksm(len,mod-2);
		for(int i=0;i<len;++i)
			f[i]=1ll*f[i]*iv%mod;
	}
}
int x[maxn],y[maxn],z[maxn];
inline void mul(int *a,int *b,int *c){
	for(int i=0;i<len;++i)x[i]=a[i],y[i]=b[i];
	ntt(x,len,1),ntt(y,len,1);
	for(int i=0;i<len;++i)z[i]=1ll*x[i]*y[i]%mod;
	ntt(z,len,0);for(int i=0;i<=n;++i)c[i]=z[i];
}
int a,b,c,f[maxn],g[maxn];
inline void getpower(int x){
	if(x==1)return;
	getpower(x>>1);
	ntt(g,len,1);
	for(int i=0;i<len;i++)
		g[i]=1ll*g[i]*g[i]%mod;
	ntt(g,len,0);
	for(int i=n+1;i<len;i++)
		g[i]=0;
	if(x&1){
		ntt(g,len,1);
		for(int i=0;i<len;i++)
			g[i]=1ll*g[i]*f[i]%mod;
		ntt(g,len,0);
		for(int i=n+1;i<len;i++)
			g[i]=0;
	}
}
signed main(){
	n=read(),m=read();
	for(;len<=n+n;len<<=1);
	for(int i=0;i<len;i++)
		tr[i]=(tr[i>>1]>>1)|((i&1)?len>>1:0);
	fac[0]=ifc[0]=inv[1]=1;
	for(int i=1;i<=max(n,m);++i)
		fac[i]=1ll*fac[i-1]*i%mod;
	for(int i=2;i<=max(n,m);++i)
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=1;i<=max(n,m);++i)
		ifc[i]=1ll*ifc[i-1]*inv[i]%mod;
	for(int i=0;i<=n;i++)g[i]=f[i]=inv[i];
	ntt(f,len,1);getpower(m);
	for(int i=0;i<=n;++i)
		printf("%lld ",1ll*g[i]*fac[i]%mod*ifc[m]%mod);
	return 0;
}
posted @ 2021-02-25 21:23  syzf2222  阅读(95)  评论(0编辑  收藏  举报