【题解 P4550】 收集邮票
收集邮票
题目描述
有 \(n\) 种不同的邮票,皮皮想收集所有种类的邮票。唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且买到的邮票究竟是 \(n\) 种邮票中的哪一种是等概率的,概率均为 \(1/n\)。但是由于凡凡也很喜欢邮票,所以皮皮购买第 \(k\) 次邮票需要支付 \(k\) 元钱。
现在皮皮手中没有邮票,皮皮想知道自己得到所有种类的邮票需要花费的钱数目的期望。
输入格式
一行,一个数字 \(N\)(\(N \le 10000\))。
输出格式
输出要付出多少钱,保留二位小数。
样例 1
样例输入 1
3
样例输出 1
21.25
算法过程
一看就是一道期望 \(DP\) 。
定义 \(f_i\) 为已经买 \(i\) 种邮票的还需要次数,\(g_i\) 为已经买 \(i\) 种邮票的还需要花费。
显然,\(f_n=0\) 。
很明显,\(f_i\) 有 \(\frac{i}{n}\) 的概率买到之前的,即为 \(\frac{i}{n}\times f_i\) ,有 \(\frac{n-i}{n}\) 买到新的,即为 \(\frac{n-i}{n} \times f_{i+1}\) 。
所以 \(f_i=\frac{i}{n}\times f_i+\frac{n-i}{n} \times f_{i+1}+1\) 。
即为 $ f_i=f_{i+1}+\frac{n}{n-i}$ 。
而 \(g_i\) 同理,若是之前的,即为已有的花费加上这一次的花费,分别是 \(g_i\) 与 \(f_i+1\) ,就是 \(\frac{i}{n}\times (g_i+f_i+1)\) ,买到新的同上。
所以,\(g_i=\frac{i}{n}\times (g_i+f_i+1)+\frac{n-i}{n}\times (g_{i+1}+f_{i+1}+1)\) 。
化简,\(g_i=\frac{i}{n-i} \times f_i+g_{i+1}+f_{i+1}+\frac{n}{n-i}\)
Code
#include<bits/stdc++.h>
using namespace std;
long long n,a[1000005];
double f[1000005],l[1000005];
int main()
{
scanf("%lld",&n);
for(int i=n-1;i>=0;i--)
{
f[i]=f[i+1]+(1.0*n)/(1.0*(n-i));
l[i]=(1.0*i)/(1.0*(n-i))*(f[i]+1)+l[i+1]+f[i+1]+1;
}
printf("%.2lf",l[0]);
return 0;
}