高中时我们一定学过期望的计算公式,十分简单易懂,但是一旦 趋于无穷,我们又该如何去解决这种期望问题呢。
为此我曾看了许多博客文章但是始终没有答案,其中有这么一篇更是引起了我的困惑https://blog.youkuaiyun.com/weixin_62528401/article/details/131615568
其中最简单的例题一就把我难住了为什么,他写到


我一直在想这个式子是怎么来的,可是越想越迷糊,直到我不断加深对dp的了解,我有了自己的理解。
是的,就应该是这样才对,由已知的状态去推出未知的状态,同时在状态转移时加上边权(代表多摸了一次),体现线性dp的特征
同样的我们来看这题https://atcoder.jp/contests/abc382/tasks/abc382_e


如何理解呢,其实就是摸到k个指定球的期望次数,思路写注释里了
#include <bits/stdc++.h>
using namespace std;
using ll =long long;
const int N=1e5;
double a[N],dp[5010][5010],g[5010];
inline void solve() {
int n,x; cin >> n >> x;
for(int i=1;i<=n;i++) cin >> a[i],a[i]*=0.01;
// dp[i][j] 前 i 张卡里恰好有 j 张稀有卡的概率
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=i;j++){
dp[i][j]+=dp[i-1][j-1] * a[i];
dp[i][j]+=dp[i-1][j] * (1-a[i]);
}
}
// g[i] 期望抽 g[i] 包可以保证至少有 i 张稀有卡
// g[0]=0; g[x] = dp[n][j] * g[x-j] + 1 (j--[1,x])
for(int i=1;i<=x;i++){
double res=1;
for(int j=1;j<i;j++){
res+=dp[n][j]*g[i-j];
}
g[i]=res/(1-dp[n][0]);
}
cout <<fixed << setprecision(10)<<g[x];
}
int main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int T = 1;
// std::cin >> T;
while (T--) solve();
return 0;
}
多想,多做才是王道
829



被折叠的 条评论
为什么被折叠?



