[AGC038E] Gachapon
\(\text{Problem}:\)Gachapon
\(\text{Solution}:\)
设 \(t_{i}\) 表示 \(i\) 出现了至少 \(B_{i}\) 次的期望时间,答案即为 \(\max(S)\)。考虑 \(\min-\max\) 容斥:
现在的问题就是对于给定的集合 \(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\),其概率为:
枚举所有可能的 \(k\) 及 \(w\) 即可得到 \(\min(T)\),答案为:
发现 \(\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\) 里面的东西),有转移:
边界由于 \((-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;
}