LGP5860题解

考虑了很久的背包转 GF 手足无措 手足相惜,然后思考组合意义直接算出来了。。。

好吧好像是可以 GF 的。。。

比较显然的是答案是这个东西:

\[(\sum[x^iy^{2i-2}])\prod(1+xy^{d_i}) \]

考虑 \(1\leq d_i\),所以我们直接把指数减一个:

\[(\sum[x^{i-2}])\prod(1+x^{d_i-1}) \]

然后。。。显然 \(i\) 的上界是 \(n\),那么把后面的东西求出来之后求其 \(0\sim n-2\) 次项之和即可。

后面这玩意儿长得很像欧拉变换,于是用类似的方式处理一下:

\[\prod(1+x^i)^{f_i} \]

\[\exp(\sum f_i\ln(1+x^i)) \]

\[\ln(1+x^i) \]

\[\int\frac{ix^{i-1}}{1+x^i} \]

\[i\int\sum_{k=0}(-1)^kx^{(k+1)i-1} \]

\[\frac{i\sum_{k=1}(-1)^{k-1}x^{ik}}{ik} \]

\[\frac{\sum_{k=1}(-1)^{k-1}x^{ik}}{k} \]

\[\exp(\sum_{i=0}^{n-1}f_i\sum_{j=0}(-1)^{j-1}\frac{x^{ij}}{j} \]

\[\exp(\sum_{i=0}^{n-1}(-1)^{i-1})\sum_{j=0}f_j\frac{x^{ij}}{j} \]

\[\exp(\sum\frac{(-1)^{i-1}F(x^i)}{i}) \]

如果考虑组合意义的话:

考虑选若干叶子结点,对于度数为 \(2\) 的节点想选多少选多少,然后选择剩余节点时相当于令叶子结点数量减少 \(d_i-2\),能得到与上面相似的结论。

#include<cstdio>
#include<cctype>
#define IMP(lim,act) for(int qwq=(lim),i=0;i^qwq;++i)act
const int M=1<<20|5,mod=998244353;
int n,F[M];
int fac[M<<1],ifac[M<<1],inv[M<<1],buf[M<<1],*w[25];
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]);
	inv[0]=inv[1]=1;for(int i=2;i^n;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	fac[0]=ifac[0]=1;for(int i=1;i^n;++i)fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i-1]*inv[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 void Der(int*f,const int&n){
	IMP(n-1,f[i]=1ll*f[i+1]*(i+1)%mod);f[n-1]=0;
}
inline void Int(int*f,const int&n){
	for(int i=n-1;i>=0;--i)f[i+1]=1ll*f[i]*inv[i+1]%mod;f[0]=0;
}
inline void Ln(int*f,const int&n){
	static int g[M];const int&len=Getlen(n+n-2);IMP(n,g[i]=f[i]);Der(f,n);Inv(g,n);
	DFT(f,len);DFT(g,len);IMP(1<<len,g[i]=1ll*g[i]*f[i]%mod);IDFT(g,len);IMP(1<<len,f[i]=0);
	IMP(n-1,f[i]=g[i]);Int(f,n-1);IMP(1<<len,g[i]=0);
}
inline void Exp(int*f,const int&n){
	static int b1[M],b2[M],b3[M];const int&m=Getlen(n);b1[0]=1;
	for(int len=1;len<=m;++len){
		IMP(1<<len-1,b3[i]=b2[i]=b1[i]);Ln(b2,1<<len);IMP(1<<len,b2[i]=Del(f[i],b2[i]));++b2[0];
		DFT(b2,len);DFT(b3,len);IMP(1<<len,b2[i]=1ll*b2[i]*b3[i]%mod);IDFT(b2,len);
		IMP(1<<len-1,b1[1<<len-1|i]=b2[1<<len-1|i]);
	}
	IMP(n,f[i]=b1[i]);IMP(1<<m,b1[i]=b2[i]=b3[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 int binom(const int&n,const int&m){
	return 1ll*ifac[m]*ifac[n-m]%mod*fac[n]%mod;
}
signed main(){
	int c1(0),c2(0),ans(0);n=read();for(int d,i=0;i^n;++i)d=read(),d==1?++c1:d==2?++c2:++F[d-2];init(n<<1);
	for(int i=n-1;i>=1;--i)for(int j=2;i*j<n;++j)F[i*j]=(F[i*j]+1ll*(j&1?inv[j]:mod-inv[j])*F[i])%mod;
	Exp(F,n);for(int i=1;i<n&&i<c1;++i)ans=(ans+1ll*binom(c1,i+1)*F[i-1])%mod;printf("%d",1ll*pow(2,c2)*ans%mod);
}
posted @ 2022-07-04 16:15  Prean  阅读(15)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};