原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1426
收集邮票
Description
有n种不同的邮票,皮皮想收集所有种类的邮票。唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且买到的邮票究竟是n种邮票中的哪一种是等概率的,概率均为1/n。但是由于凡凡也很喜欢邮票,所以皮皮购买第k张邮票需要支付k元钱。现在皮皮手中没有邮票,皮皮想知道自己得到所有种类的邮票需要花费的钱数目的期望。
Input
一行,一个数字N N<=10000
Output
要付出多少钱. 保留二位小数
Sample Input
3
Sample Output
21.25
题解
设 f[i] f [ i ] 为买到 i i 张时还需要购买的次数,为买到 i i 张时还需要花的钱。
在买到第张时,考虑买第
i+1
i
+
1
张,我们有可能买到自己已经有的邮票,还有可能买到自己没有的邮票,于是买到第
i
i
张时还需要买的次数的期望如下:
in i n 为买到自己已经有的邮票的概率, n−in n − i n 为买到自己没有的邮票的概率, +1 + 1 即多买了一次,我们化简上面的式子:
f[i]−f[i]×in=f[i+1]×n−in+1 f [ i ] − f [ i ] × i n = f [ i + 1 ] × n − i n + 1
f[i]×n−in=f[i+1]×n−in+1 f [ i ] × n − i n = f [ i + 1 ] × n − i n + 1
f[i]=f[i+1]+nn−i f [ i ] = f [ i + 1 ] + n n − i
又因为我们已知 f[n]=0 f [ n ] = 0 ,因此我们可以倒推。
同理,
g[i]
g
[
i
]
的推导跟
f[i]
f
[
i
]
类似,也分为买到自己已有的邮票和没有的邮票两种情况:
因为第 i i 次买邮票需要花费元,所以买 i+1 i + 1 张邮票时要加上购买的次数,即 f f ,乘以概率之类的操作同上,化简如下:
n−ing[i]=inf[i]+n−in(g[i+1]+f[i+1])+1 n − i n g [ i ] = i n f [ i ] + n − i n ( g [ i + 1 ] + f [ i + 1 ] ) + 1
g[i]=in−if[i]+g[i+1]+f[i+1]+nn−i g [ i ] = i n − i f [ i ] + g [ i + 1 ] + f [ i + 1 ] + n n − i
g[n] g [ n ] 仍然是0,我们还是可以倒推。
代码
#include<bits/stdc++.h>
#define db double
using namespace std;
const int M=1e4+5;
int n;
db f[M],g[M];
void in()
{scanf("%d",&n);}
void ac()
{
for(int i=n-1;i>=0;--i)
f[i]=f[i+1]+(db)n/(n-i);
for(int i=n-1;i>=0;--i)
g[i]=g[i+1]+f[i+1]+(db)i/(n-i)*f[i]+(db)n/(n-i);
printf("%.2lf",g[0]);
}
int main()
{
in();ac();
return 0;
}