bzoj1426/洛谷P4550 收集邮票

题目分析

期望的通常套路是逆推。

f ( i ) f(i) f(i)表示当前手头已经有 i i i种邮票的情况下,收集满邮票期望要买多少次。那么 f ( i ) = i n f ( i ) + n − i n f ( i + 1 ) + 1 f(i)=\frac{i}{n} f(i)+\frac{n-i}{n} f(i+1)+1 f(i)=nif(i)+nnif(i+1)+1,即 f ( i ) = f ( i + 1 ) + n n − i f(i)=f(i+1)+\frac{n}{n-i} f(i)=f(i+1)+nin

g ( i ) g(i) g(i)表示当前手头已经有 i i i种邮票的情况下,买的第一张价格为 1 1 1,第二张价格为 2 2 2,以此类推,期望要花多少钱。那么我做完“买邮票”这个操作后,到达的新状态下,继续决策买的邮票的价格都会加1,算总共加的期望,可以得到式子:

g ( i ) = i n ( g ( i ) + f ( i ) ) + n − i n ( g ( i + 1 ) + f ( i + 1 ) ) + 1 g(i)=\frac{i}{n} (g(i)+f(i)) + \frac{n-i}{n} (g(i+1)+f(i+1))+1 g(i)=ni(g(i)+f(i))+nni(g(i+1)+f(i+1))+1

即:

g ( i ) = i n − i f ( i ) + g ( i + 1 ) + f ( i + 1 ) + n n − i g(i)=\frac{i}{n-i} f(i)+g(i+1)+f(i+1)+\frac{n}{n-i} g(i)=niif(i)+g(i+1)+f(i+1)+nin

代码

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值