[AGC038E] Gachapon

VI.[AGC038E] Gachapon

因为模型同III.重返现世长得很像,所以我们也来考虑minmax容斥。

首先,我们仍然翻出式子

\[\max(\mathbb S)=\sum\limits_{\mathbb{T\subseteq S}}(-1)^{|\mathbb T|+1}\min(\mathbb T) \]

然后,我们考虑计算 \(\text E(\min\mathbb T)\)

我们发现,对于某个 \(\mathbb T\),它的 \(\min\) 的实际意义是其中一个元素率先全部被生成。而当该元素被生成完时,其它 \(\mathbb T\) 中元素生成的数量都不能达到 \(b_i\)。因此这启发我们要枚举结束时 \(\mathbb T\) 中每个元素被生成的数量。设此数组为 \(\{c\}\)

我们发现,由 \(\mathbb T\) 来推出所有合法的 \(\{c\}\) 是困难的,但是由 \(\{c\}\) 来反推 \(\mathbb T\) 则是简单的——因为在处理 \(\{c\}\) 的时候肯定顺手就把 \(\mathbb T\) 的位置给记录了。于是我们考虑给定了一个 \(\{c\}\),计算其作为其对应的 \(\mathbb T\) 的终止状态的概率。

首先,我们考虑令 \(a'\) 表示那个率先被全部生成的数的 \(a\)。显然,\(c'=b'\),但是因为钦定了最后一个生成的数是 \(a'\),因此我们令 \(c'\) 强制减一,这样现在所有 \(c\) 中元素间顺序便可以任意调换。

考虑恰好生成 \(c\) 中所有元素的概率,是

\[\dfrac{\prod a^c}{(\sum a)^{\sum c}} \]

但是,因为元素间有序,所以还要乘上多项式系数

\[\dfrac{(\sum c)!}{\prod c!} \]

同时,别忘记最后一个生成的数必须是 \(a'\),因此还有

\[\dfrac{a'}{\sum a} \]

考虑生成此种情形期望需要生成多少个数:因为期望 \(\dfrac{S}{\sum a}\)(依照题面,有定义 \(S=\sum\limits_{i=0}^{n-1}a_i\))次会摇到一个来自 \(\mathbb T\) 中的元素,所以期望 \((\sum c+1)\times\dfrac S{\sum a}\) 次就能摇全。

所有东西怼一块,得到

\[(\sum c+1)\times\dfrac S{\sum a}\times\dfrac{\prod a^c}{(\sum a)^{\sum c}}\times\dfrac{(\sum c)!}{\prod c!}\times\dfrac{a'}{\sum a} \]

稍微整理一下,把与单个的 \(a\)\(\sum a\) 有关的拆开来放

\[S\times\dfrac{(\sum c+1)\times(\sum c)!}{(\sum a)^{\sum c+2}}\times\dfrac{\prod a^c\times a'}{\prod c!} \]

最开头的是常数,中间一个分数是与 \(\sum c,\sum a\) 有关的东西,最后一坨是与单个的 \(a\)\(c\) 有关的东西。

于是我们考虑DP。设 \(f_{i,j,k,odd,0/1}\) 表示当前DP到位置 \(i\)\(\sum c=j,\sum a=k\)\(|\mathbb T|\) 的奇偶性为 \(odd\),且 \(a'\) 未/已被决定。

转移分两种:确定 \(a'\) 的转移和不确定 \(a'\) 的转移。确定 \(a'\) 的转移就强制你有 \(c=b-1\)(注意到我们之前已经令 \(c'\) 强制减一了),不确定 \(a'\) 的转移,可以枚举 \(c\in[0,b)\)

乍一看,\(i,j,k\) 三维都是 \(400\),剩下两维都是常数,但还要枚举一个 \(c\),这不是 \(400^4\) 的吗?

一开始我也苦恼了很久,但后来想到 \(i\) 维和 \(c\) 维加在一块等于 \(\sum b=400\),因此实际是 \(400^3\) 的。

注意将一些共同的东西提前算出可以减少常数。

代码:

#include<bits/stdc++.h> 
using namespace std;
const int mod=998244353;
int ksm(int x,int y=mod-2){int z=1;for(;y;y>>=1,x=1ll*x*x%mod)if(y&1)z=1ll*z*x%mod;return z;}
int n,a[410],b[410],A,B,f[410][410][2][2],fac[410],inv[410],res;
void ADD(int &x,int y){x+=y;if(x>=mod)x-=mod;}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]),A+=a[i],B+=b[i];
	fac[0]=1;for(int i=1;i<=B;i++)fac[i]=1ll*fac[i-1]*i%mod;
	inv[B]=ksm(fac[B]);for(int i=B;i;i--)inv[i-1]=1ll*inv[i]*i%mod;
//	for(int i=0;i<=B;i++)printf("%d ",fac[i]);puts("");
//	for(int i=0;i<=B;i++)printf("%d ",inv[i]);puts("");
	f[0][0][0][0]=1;
	for(int i=1;i<=n;i++){
		int tmp=1ll*ksm(a[i],b[i]-1)*inv[b[i]-1]%mod*a[i]%mod;
		for(int j=B;j>=0;j--)for(int k=A;k>=0;k--)for(int odd=0;odd<2;odd++){
	//		if(f[j][k][odd][0])printf("(%d,%d,%d,%d,%d):%d\n",i-1,j,k,odd,0,f[j][k][odd][0]);
	//		if(f[j][k][odd][1])printf("(%d,%d,%d,%d,%d):%d\n",i-1,j,k,odd,1,f[j][k][odd][1]);
			if(f[j][k][odd][0]){
	//			printf("%d %d %d %d\n",f[j][k][odd][0],ksm(a[i],b[i]-1),inv[b[i]-1],a[i]);
				ADD(f[j+b[i]-1][k+a[i]][odd^1][1],1ll*f[j][k][odd][0]*tmp%mod);
				for(int l=0,m=1;l<b[i];l++,m=1ll*m*a[i]%mod)ADD(f[j+l][k+a[i]][odd^1][0],1ll*f[j][k][odd][0]*m%mod*inv[l]%mod);
			}
			if(f[j][k][odd][1])for(int l=0,m=1;l<b[i];l++,m=1ll*m*a[i]%mod)ADD(f[j+l][k+a[i]][odd^1][1],1ll*f[j][k][odd][1]*m%mod*inv[l]%mod);
		}	
	}
	for(int j=0;j<=B;j++)for(int k=1;k<=A;k++)for(int odd=0;odd<2;odd++){
		int tmp=1ll*f[j][k][odd][1]*(j+1)%mod*A%mod*ksm(ksm(k,j+2))%mod*fac[j]%mod;
//		printf("%d,%d,%d:%d\n",j,k,odd,tmp);
//		printf("%d %d %d %d %d\n",f[j][k][odd][1],(j+1),A,ksm(ksm(k,j+2)),fac[j]);
		if(odd&1)(res+=tmp)%=mod;else (res+=mod-tmp)%=mod;
	}
	printf("%d\n",res);
	return 0;
}
posted @ 2021-04-09 14:24  Troverld  阅读(168)  评论(0编辑  收藏  举报