题目传送门
用(f_i)表示已经买了i种,到买齐邮票的期望买的张数。
用(g_i)表示已经买了i种,到买齐邮票的期望花的价格。
所以
(f_i=(f_i+1)*frac{i}{n}+(f_{i+1}+1)*frac{n-i}{n})
(g_i=(g_i+f_i+1)*frac{i}{n}+(g_{i+1}+f_{i+1}+1)*frac{n-i}{n})
(f_i)有(frac{i}{n})的概率买到以前的,有(frac{n-i}{n})的概率买到新的邮票。
(g_i)有(frac{i}{n})的概率买到以前的,而买到以前的对答案的贡献为(g_i+f_i+1),即原期望+买这一次的期望花费;有(frac{n-i}{n})的概率买到新的,而买到新的对答案的贡献为(g_{i+1}+f_{i+1}+1),即从(i+1)到(n)的期望花费+买这一次的期望花费。
再移项化简式子即可。
这个的Markdown优化版.(得到了授权)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
double f[10001],g[10001];
int n;
inline int _read() {
int s = 0,w = 1;
char p = getchar();
while(p < '0' || p > '9') {
if(p == '-1') w = -1;
p = getchar();
}
while(p >= '0' && p <= '9') {
s = s * 10 + (p - '0');
p = getchar();
}
return s * w;
}
int main() {
n = _read();
double nn = n,p;
for(int i = n - 1;i >= 0; i--)
p = i * 1.0,f[i] = f[i+1] + 1 + (double)(p / (nn - p));
for(int i = n - 1;i >= 0; i--)
p = i * 1.0,g[i] = g[i+1] + f[i+1] + 1 + (f[i] + 1) * (double)(p / (nn - p));
printf("%.2lf",g[0]);
return 0;
}