题面
解法
有一定思维难度的期望dp
- 首先,如果直接强行求最后期望花钱的数量是不太可行的
- 那么,我们不妨先求出期望买的张数,然后就可以比较方便地求出最后的答案
- 设 表示已经收集到 种不同的邮票,还需要再购买的邮票数的期望值,不妨就假设那 种邮票就是前 种,因为我们并不关心到底购买到的是哪一种
- 那么,关于 的转移方程是比较容易得到的,考虑下一次买到的是什么,有 的概率会买到之前的 张,有 的概率会买到剩余没有被买到过的
- 所以,我们就可以得到 。把这个式子转化一下,就变成 。得到这个式子可以根据期望的线性性。
- 然后,我们再设 表示已经收集到 种不同的邮票,还需要购买的期望代价
- 可以发现, 的转移其实和 很类似,可以得到 ,稍微移项一下就变成
- 那么,我们最后的答案就是
- 本题主要运用期望的线性性,这个性质是解决期望问题的关键
- 解决期望问题一般都是倒推
- 时间复杂度:
代码
#include <bits/stdc++.h>
#define double long double
#define N 10010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
x = 0; int f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
double f[N], g[N];
int main() {
int n; read(n); f[n] = g[n] = 0;
for (int i = n - 1; ~i; i--) {
f[i] = f[i + 1] + (double)n / (n - i);
g[i] = (double)i / (n - i) * f[i] + g[i + 1] + f[i + 1] + (double)n / (n - i);
}
cout << fixed << setprecision(2) << g[0] << "\n";
return 0;
}