[AGC038E] Gachapon

\(\text{Problem}:\)Gachapon

\(\text{Solution}:\)

\(t_{i}\) 表示 \(i\) 出现了至少 \(B_{i}\) 次的期望时间,答案即为 \(\max(S)\)。考虑 \(\min-\max\) 容斥:

\[\max(S)=\sum\limits_{T\subseteq S}(-1)^{\lvert T\rvert-1}\min(T) \]

现在的问题就是对于给定的集合 \(T\),求出 \(\min(T)\)

巧妙地转换一下 \(\min(T)\) 的含义。设 \(w_{i}\) 表示 \(i\) 出现的次数,\(\min(T)\) 等价于处于 \(\forall i\in[1,n],w_{i}<B_{i}\) 状态的期望时间加 \(1\)(要把初始状态算上)。

设选到集合 \(T\) 内的数的概率为 \(P=\dfrac{\sum_{i\in T}A_{i}}{S}\),选到集合 \(T\) 内的数 \(k\) 次。显然操作次数为 \(\dfrac{k}{P}\),与满足 \(\forall i\in[1,n],w_{i}<B_{i}\) 的概率相乘就是对 \(\min(T)\) 的贡献。对于一组合法的 \(w\),其概率为:

\[\binom{k}{w_{1},w_{2},...,w_{\lvert T\rvert}}\times \prod\limits_{i\in T}\left(\cfrac{A_{i}}{\sum_{j\in T}A_{j}}\right)^{w_{i}}=k!\times \left(\sum\limits_{i\in T}A_{i}\right)^{-k}\times \prod\limits_{i\in T}\cfrac{A_{i}^{w_{i}}}{w_{i}!} \]

枚举所有可能的 \(k\)\(w\) 即可得到 \(\min(T)\),答案为:

\[\max(S)=\sum\limits_{T\subseteq S}(-1)^{\lvert T\rvert-1}\left(\sum\limits_{k=0}^{\sum_{i\in T}B_{i}-1}\cfrac{k!}{P}\times \left(\sum\limits_{i\in T}A_{i}\right)^{-k}\times \prod\limits_{\sum_{i\in T} w_{i}=k}\cfrac{A_{i}^{w_{i}}}{w_{i}!}\right) \]

发现 \(\left(\sum\limits_{i\in T}A_{i}\right)^{-k}\) 这东西非常难以直接维护,故考虑 \(dp\) 求出系数。设 \(f_{i,j,k}\) 表示前 \(i\) 个数,\(\sum A_{i}=j\)\(\sum w_{i}=k\) 的贡献之和(指后面 \(\prod\) 里面的东西),有转移:

\[f_{i,j,k}=f_{i-1,j,k}-\sum\limits_{x=0}^{\min\{B_{i}-1,k\}}f_{i-1,j-A_{i},k-x}\times \cfrac{A_{i}^{x}}{x!} \]

边界由于 \((-1)^{-1}=-1\),得 \(f_{0,0,0}=-1\)

最后乘上系数计入答案即可。总时间复杂度为 \(O(n\cdot\sum A_{i}\cdot \sum B_{i})\),本题 \(\sum A_{i},\sum B_{i}\)\(n\) 同阶,故也可以看作 \(O(n^3)\)

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=405, Mod=998244353;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,A[N],B[N],F[N][N][N],pw[N][N],SA,SB,fac[N+5],inv[N+5];
inline int ksc(int x,int p) { int res=1; for(;p;p>>=1, x=1ll*x*x%Mod) if(p&1) res=1ll*res*x%Mod; return res; }
signed main()
{
	fac[0]=1;
	for(ri int i=1;i<=N;i++) fac[i]=1ll*fac[i-1]*i%Mod;
	inv[N]=ksc(fac[N],Mod-2);
	for(ri int i=N;i;i--) inv[i-1]=1ll*inv[i]*i%Mod;
	n=read();
	for(ri int i=1;i<=n;i++) A[i]=read(), B[i]=read(), SA+=A[i], SB+=B[i];
	for(ri int i=1;i<=SA;i++)
	{
		pw[i][0]=1;
		for(ri int j=1;j<=SB;j++) pw[i][j]=1ll*pw[i][j-1]*i%Mod;
	}
	F[0][0][0]=Mod-1;
	for(ri int i=1;i<=n;i++)
	{
		for(ri int j=0;j<=SA;j++)
		{
			for(ri int k=0;k<SB;k++)
			{
				F[i][j][k]=F[i-1][j][k];
				if(j<A[i]) continue;
				for(ri int x=0;x<B[i]&&x<=k;x++)
				{
					F[i][j][k]=(F[i][j][k]-1ll*F[i-1][j-A[i]][k-x]*pw[A[i]][x]%Mod*inv[x]%Mod+Mod)%Mod;
				}
			}
		}
	}
	int ans=0;
	for(ri int i=0;i<=SA;i++)
	for(ri int j=0;j<=SB;j++)
	ans=(ans+1ll*F[n][i][j]*SA%Mod*fac[j]%Mod*ksc(ksc(i,j+1),Mod-2)%Mod)%Mod;
	printf("%d\n",ans);
	return 0;
}
posted @ 2021-04-20 19:55  zkdxl  阅读(50)  评论(0编辑  收藏  举报