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}\)。代入回去得到总式子(以下进行多次变换):
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);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通