题目大致意思: 总共有n种邮票,每选一张邮票,邮票的价格会加一,邮票的初始值是1,最后问拿完n种邮票的期望价格。
思路:
发表一下看这个题题解的感想:这个题太仙了,概率dp的套路司空见惯就是把数组定义成已经考虑前i个—到n的期望。那么我们先开一个数组来记录,f[]记录从已经选了i个从第i种开始选到第n种的期望步数,那么转移就来了,只有两种情况,第一种是选到了之前选了邮票,第二种选了之前没选的邮票,
f[i]=(i/n)(f[i]+1)+((n-1)/n) (f[i+1]+1),为什么要在每个里面加一呢,代表走出第i种决策的一步。f数组还是比较好想的,但是我们最后要求的是期望花费呀,秉承着要求什么就开什么的原则,那么我们另外一个数组,代表选了i种到选完n种的花费,两个数组的初始化都是f[n]=0,g[n]=0,概率dp的套路我目前看到的都是反着推的,递推式就是
g[i]=i/n(g[i]+f[i]+1)+(n-i)/n(g[i+1]+f[i+1]+1)**,当时一直想不明白 这个f数组有啥关系呀,但仔细想想,我们从这个状态转移出去,如果还是转移到原来状态,这一步是第一步花费是1,但是因为前面说的邮票买的越多价格越高,对g产生了后效性,由于之前算的要走k步,里面的每一步都会有1这个增量,所以就是加了f[i].
代码很简单,重在推下来的思路:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<vector>
#include<queue>
#include<stack>
#include<iostream>
#include<sstream>
#include<set>
#define x first
#define y second
#define int long long 
#define lson u<<1
#define rson u<<1|1
#define pb push_back
#define pu pushup
#define mk make_pair
using namespace std;
#define ll long long
#define mod 1000000007
inline int read(){
   
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){
   if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
const int N=10010;
double f[N],g[N];
signed main()
{
   
	int n;
	cin>>n;
	f[n]=g[n]=0;
	for(int i=n-1;i>=0;i--)
		f[i]=f[i+1]+1.0*n/(n-i);
	for(int i=n-1;i>=0;i--)
		g[i]=1.0*n/(n-i)+1.0*i/(n-i)*f[i]+f[i+1]+g[i+1];
	printf("%.2lf\n",g[0]);
}