LGP5162题解

\(f[n][m]\) 为将 \(n\) 个有标号元素放入 \(m\) 个有标号集合(不能空) 的方案数。

答案就是 \(\frac{\sum i\times f[n][i]}{\sum f[n][i]}\)

来考虑这个鬼东西怎么算。。。容易发现 \(f[n][m]=n![x^n](e^x-1)^{m}\)

那么有 \(n![x^n]\sum_{i=1}^{n}(e^x-1)^{i}=n![x^n]\frac{1}{1-(e^x-1)}-1=n![x^n]\frac{1}{2-e^x}\)

上面那个就是 \([x^n]\sum_{i=1}^{n}i(e^x-1)^{i}\)

我们知道有 \(\sum_{i=0}(i+1)x^i=\frac{1}{(1-x)^2}\),那么这里就有:

\[[x^n]\frac{e^x-1}{(1-(e^x-1))^2}-1 \]

\[[x^n]\frac{e^x-1}{(2-e^x)^2} \]

两个都只需要做一遍同一个多项式的多项式求逆,以及分子多做两次卷积。

复杂度 \(O(n\log n)\)

#include<cstdio>
#include<cctype>
#define IMP(lim,act) for(int qwq=(lim),i=0;i^qwq;++i)act
const int M=1<<19|5,mod=998244353;
int t,n[M],F[M],G[M],T[M],ans[M];int ifac[M<<1],buf[M<<2],*w[20];
inline int Getlen(const int&n){
	int len(0);while((1<<len)<n)++len;return len;
}
inline int Add(const int&a,const int&b){
	return a+b>=mod?a+b-mod:a+b;
}
inline int Del(const int&a,const int&b){
	return b>a?a-b+mod:a-b;
}
inline void swap(int&a,int&b){
	int c=a;a=b;b=c;
}
inline int pow(int a,int b=mod-2){
	int ans(1);for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;
}
inline void init(const int&n){
	const int&m=Getlen(n);int*now=buf;w[m]=now;now+=1<<m;
	w[m][0]=1;w[m][1]=pow(3,mod-1>>m+1);for(int i=2;i^1<<m;++i)w[m][i]=1ll*w[m][i-1]*w[m][1]%mod;
	for(int k=m-1;k>=0&&(w[k]=now,now+=1<<k);--k)IMP(1<<k,w[k][i]=w[k+1][i<<1]);
	ifac[0]=ifac[1]=1;for(int i=2;i<=n;++i)ifac[i]=1ll*(mod-mod/i)*ifac[mod%i]%mod;
	for(int i=1;i<=n;++i)ifac[i]=1ll*ifac[i-1]*ifac[i]%mod;
}
inline void DFT(int*f,const int&M){
	const int&n=1<<M;
	for(int len=n>>1,d=M-1;d>=0;--d,len>>=1)for(int k=0;k^n;k+=len<<1){
		int*W=w[d],*L=f+(k),*R=f+(k|len),x,y;IMP(len,(x=*L,y=*R)),*L++=Add(x,y),*R++=1ll**W++*Del(x,y)%mod;
	}
}
inline void IDFT(int*f,const int&M){
	const int&n=1<<M;
	for(int len=1,d=0;d^M;++d,len<<=1)for(int k=0;k^n;k+=len<<1){
		int*W=w[d],*L=f+(k),*R=f+(k|len),x,y;IMP(len,(x=*L,y=1ll**W++**R%mod)),*L++=Add(x,y),*R++=Del(x,y);
	}
	const int&k=pow(n);IMP(n,f[i]=1ll*f[i]*k%mod);for(int i=1;(i<<1)<n;++i)swap(f[i],f[n-i]);
}
inline void Inv(int*f,const int&n){
	static int b1[M],b2[M],b3[M];const int&m=Getlen(n);b1[0]=pow(f[0]);
	for(int len=1;len<=m;++len){
		IMP(1<<len-1,b2[i]=2ll*b1[i]%mod);IMP(1<<len,b3[i]=f[i]);
		DFT(b1,len+1);DFT(b3,len+1);IMP(1<<len+1,b1[i]=1ll*b1[i]*b1[i]%mod*b3[i]%mod);IDFT(b1,len+1);
		IMP(1<<len,b1[i]=Del(b2[i],b1[i])),b3[i]=b3[1<<len|i]=b1[1<<len|i]=0;
	}
	IMP(n,f[i]=b1[i]);IMP(1<<m,b1[i]=b2[i]=0);
}
inline int read(){
	int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline void write(int n){
	static char s[15];int top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top]),--top);putchar(10);
}
signed main(){
	int m(0);t=read();for(int i=1;i<=t;++i)n[i]=read(),n[i]>m&&(m=n[i]);++m;init(m+m+m+1);
	for(int i=0;i<=m;++i)F[i]=mod-ifac[i],G[i]=ifac[i];F[0]=1;G[0]=0;Inv(F,m+1);IMP(m+1,T[i]=F[i]);
	const int&len=Getlen(m+m+m+1);DFT(T,len);DFT(G,len);IMP(1<<len,G[i]=1ll*T[i]*T[i]%mod*G[i]%mod);IDFT(G,len);
	for(int i=1;i<=m;++i)ans[i]=1ll*G[i]*pow(F[i])%mod;for(int i=1;i<=t;++i)write(ans[n[i]]);
}
posted @ 2022-07-05 19:47  Prean  阅读(14)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};