[Gym 102978H] Harsh Comments
Gym - 102978H
tag:背包dp,概率期望,minmax反演
题意
有\(n\)个\(A\)物品,价值为\(a_i\),\(m\)个\(B\)物品,价值为\(b_i\)。每次等概率删掉剩余物品中的一个\(\frac{val_i}{sum_{val}\ of\ remain}\),求删完\(A\)的期望步数
\(n,m\leq100,a_i\leq 100, \sum a_i+\sum b_i< 998244353\)
题解
考虑另一种做法,minmax反演
答案为\(max\{t_i\}=\sum_{S}(-1)^{|S|-1}min\{t_i\}\),
然后\(min\{E_i\}\)相当于只有一个\(A\)物品,价值为\(\sum E_i\),其余全是\(B\)物品。由于期望的线性性,答案为枚举一个\(B_i\)在\(A\)之前删掉的概率再加起来再加1。
\(\sum_{S}(-1)^{|S|-1}\sum_{i\not\in S}\frac{p_i}{S_{sum}+p_i}\)
\(\sum_i\sum_{sum}\frac{p_i}{sum+p_i}\sum_S[i\not\in S][sum_S=sum](-1)^{|S|-1}\)
换个枚举顺序\(\sum_i\sum_S[i\not\in S](-1)^{|S|-1}\frac{p_i}{S_{sum}+p_i}\)
考虑到此题\(n\leq100,a_i\leq100\),所以枚举\(sum\)
\(\sum_i\sum_{sum}\frac{p_i}{sum+p_i}\sum_S[i\not\in S][sum_S=sum](-1)^{|S|-1}\)
如果不考虑\([i\not\in S]\),后面一堆式子可以背包解决\(O((n+m)S)\)
考虑\([i\not\in S]\),由于此题用的背包可逆,所以直接删掉\(i\)再加入即可
#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void Read(T &n){
char ch; bool flag=false;
while(!isdigit(ch=getchar())) if(ch=='-')flag=true;
for(n=ch^48; isdigit(ch=getchar()); n=(n<<1)+(n<<3)+(ch^48));
if(flag) n=-n;
}
const int MAXN = 105;
const int MOD = 998244353;
inline int inc(int a, int b){
a += b;
if(a>=MOD) a -= MOD;
return a;
}
inline void iinc(int &a, int b){a = inc(a,b);}
inline int dec(int a, int b){
a -= b;
if(a<0) a += MOD;
return a;
}
inline void ddec(int &a, int b){a = dec(a,b);}
inline int ksm(int base, int k=MOD-2){
int res=1;
while(k){
if(k&1)
res = 1ll*res*base%MOD;
base = 1ll*base*base%MOD;
k >>= 1;
}
return res;
}
int f[10005], n, m, S, a[MAXN], b[MAXN], ans;
inline void ins(int k){for(register int i=S; i>=0; i--) ddec(f[i+k],f[i]); S += k;}
inline void del(int k){S -= k; for(register int i=0; i<=S; i++) iinc(f[i+k],f[i]);}
int main(){
Read(n); Read(m); f[0] = MOD-1;
for(register int i=1; i<=n; i++) Read(a[i]), ins(a[i]);
for(register int i=1; i<=m; i++) Read(b[i]);
for(register int i=1; i<=n; i++){
del(a[i]);
for(register int j=1; j<=S; j++) ans = (ans+1ll*a[i]*ksm(j+a[i])%MOD*f[j])%MOD;
ins(a[i]);
}
for(register int i=1; i<=m; i++) for(register int j=1; j<=S; j++) ans = (ans+1ll*b[i]*ksm(j+b[i])%MOD*f[j])%MOD;
cout<<inc(ans,1)<<endl;
return 0;
}