AT_agc038_e [AGC038E] Gachapon

题意

有一个随机数生成器,它能以 \(\frac{a_i}{\sum_i a_i}\) 的概率生成数 \(i(1\le i\le n)\)

定义一个数 \(i\) 合法当且仅当其被随机过大于等于 \(b_i\) 次。

求所有数全部合法的期望随机次数。模数 \(998244353\)

\(n,\sum a_i,\sum b_i\le 400\)

分析

套路性的考虑 min-max 容斥,\(ans=E(\max(S=\{1,2,\cdots ,n\}))=\sum_{\emptyset\neq T\subseteq S}(-1)^{|T|+1}E(\min(T))\)

现在考虑求 \(E(\min(T))\),即 \(T\) 集合内第一次出现合法的数的期望随机次数。

直接求这个东西貌似有点困难,因为你还要考虑选在 \(T\) 外面的情况。

考虑一个经典 trick,我们计算出随机选一个数选中 \(T\) 内的期望步数 \(e\)。那么我们可以视为每次花费 \(e\) 次随机以 \(\frac{a_i}{\sum_{i\in T}a_i}\) 的概率选中数 \(i\)。而众所周知 \(E(X)=\sum_{i} P(X\ge i)\)(当然这是每次步数为 \(1\) 的答案,在外面直接乘 \(e\) 即可),考虑计算步数大于等于某个数的概率并求和,拆贡献,枚举 \(c_i<b_i\),贡献为 \(\sum_{i} (\frac{a_i}{\sum_{j\in T}a_j})^{c_i}\frac{(\sum c_i)!}{\prod_i c_i!}\)。而 \(e\) 的值根据经典式子,其等于选中 \(T\) 内的数的概率 \(p\) 的倒数,即 \(\frac{\sum_{1\le i\le n}a_i}{\sum_{i\in T}a_i}\)。代入回去得到总式子(以下进行多次变换):

\[E(\max(S))=\sum_{\emptyset\neq T\subseteq S}(-1)^{|T|+1}\frac{\sum_{1\le i\le n}a_i}{\sum_{i\in T}a_i}\sum_{i\in T,0\le c_i<b_i}\prod a_i^{c_i}\left(\frac{1}{\sum a_i}\right)^{\sum c_i}\frac{(\sum c_i)!}{\prod c_i!} \]

DP,状态里记录 \(\sum a_i,\sum c_i\) 的值,容斥系数扔值里。转移考虑枚举 \(c_i\),不需要任何优化,复杂度 \(O(n^3)\)\(O(n^3\log n)\)

int n,a[maxn],b[maxn];
int fac[maxn],inv[maxn];
int ksm(int x,int y){
	int res=1;
	for(;y;y>>=1,x=x*x%mod)if(y&1)res=res*x%mod;
	return res;
}
void init(int lim){
	fac[0]=1;rep(i,1,lim)fac[i]=fac[i-1]*i%mod;
	inv[lim]=ksm(fac[lim],mod-2);per(i,lim-1,0)inv[i]=inv[i+1]*(i+1)%mod;
}
int mi[maxn][maxn];
int f[maxn][maxn][maxn];
inline void adder(int &x,int y){x+=y,x=x>=mod?x-mod:x;}
inline void suber(int &x,int y){x-=y,x=x<0?x+mod:x;}
inline void solve_the_problem(){
	n=rd(),init(400);
	int suma=0,sumb=0;
	rep(i,1,n)a[i]=rd(),b[i]=rd(),suma+=a[i],sumb+=b[i];
	rep(i,1,n){
		mi[i][0]=1;
		rep(j,1,b[i])mi[i][j]=mi[i][j-1]*a[i]%mod;
	}
	f[0][0][0]=mod-1;
	rep(i,1,n)rep(j,0,suma)rep(k,0,sumb)if(f[i-1][j][k]){
		adder(f[i][j][k],f[i-1][j][k]);
		rep(c,0,b[i]-1){
			suber(f[i][j+a[i]][k+c],f[i-1][j][k]*mi[i][c]%mod*inv[c]%mod);
		}
	}
	int ans=0;
	rep(j,1,suma)rep(k,0,sumb){
		adder(ans,f[n][j][k]*suma%mod*ksm(ksm(j,mod-2),k+1)%mod*fac[k]%mod);
	}
	write(ans);
}

作者:dcytrl

出处:https://www.cnblogs.com/dcytrl/p/18726640

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   dcytrl  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示