题目分析
期望的通常套路是逆推。
设f(i)f(i)f(i)表示当前手头已经有iii种邮票的情况下,收集满邮票期望要买多少次。那么f(i)=inf(i)+n−inf(i+1)+1f(i)=\frac{i}{n} f(i)+\frac{n-i}{n} f(i+1)+1f(i)=nif(i)+nn−if(i+1)+1,即f(i)=f(i+1)+nn−if(i)=f(i+1)+\frac{n}{n-i}f(i)=f(i+1)+n−in
设g(i)g(i)g(i)表示当前手头已经有iii种邮票的情况下,买的第一张价格为111,第二张价格为222,以此类推,期望要花多少钱。那么我做完“买邮票”这个操作后,到达的新状态下,继续决策买的邮票的价格都会加1,算总共加的期望,可以得到式子:
g(i)=in(g(i)+f(i))+n−in(g(i+1)+f(i+1))+1g(i)=\frac{i}{n} (g(i)+f(i)) + \frac{n-i}{n} (g(i+1)+f(i+1))+1g(i)=ni(g(i)+f(i))+nn−i(g(i+1)+f(i+1))+1
即:
g(i)=in−if(i)+g(i+1)+f(i+1)+nn−ig(i)=\frac{i}{n-i} f(i)+g(i+1)+f(i+1)+\frac{n}{n-i}g(i)=n−iif(i)+g(i+1)+f(i+1)+n−in
代码
#include<bits/stdc++.h>
using namespace std;
#define RI register int
typedef double db;
const int N=10005;
int n;db f[N],g[N];
int main()
{
scanf("%d",&n);
for(RI i=n-1;i>=0;--i) f[i]=f[i+1]+(db)n/(db)(n-i);
for(RI i=n-1;i>=0;--i)
g[i]=g[i+1]+f[i+1]+(db)i/(db)(n-i)*f[i]+(db)n/(db)(n-i);
printf("%.2lf\n",g[0]);
return 0;
}