bzoj1426 收集邮票

洛谷传送门

f [ i ] f[i] f[i]表示:现在我手上有 i i i种邮票,期望再买 f [ i ] f[i] f[i]张得到 n n n种邮票。

那么考虑 f [ i ] f[i] f[i]的转移:
当前这一次购买,有 i n \frac{i}{n} ni的概率摸到买过的,有 n − i n \frac{n-i}{n} nni的概率摸到没买过的。

如果摸到买过的,接下来对应的得到 n n n种邮票的期望就是 i n × f [ i ] \frac{i}{n}\times f[i] ni×f[i]

如果摸到没买过的,现在我手上就有 i + 1 i+1 i+1种邮票了。
那么接下来对应的得到 n n n种邮票的期望就是 n − i n × f [ i + 1 ] \frac{n-i}{n}\times f[i+1] nni×f[i+1]

于是乎我们得到——
f [ i ] = i n × ( f [ i ] + 1 ) + n − i n × ( f [ i + 1 ] + 1 ) f[i]=\frac{i}{n}\times(f[i]+1)+\frac{n-i}{n}\times (f[i+1]+1) f[i]=ni×(f[i]+1)+nni×(f[i+1]+1)(这里的 + 1 +1 +1对应这里的一次购买,因为走到这一步也是有消耗的)

当然,上述转移考虑的是每次花费都是 1 1 1。现在题目中要求第 k k k次的花费为 k k k
g [ i ] g[i] g[i]表示当前有 i i i种邮票,买到 n n n种邮票还需要的期望花费。
g [ i ] = i n × ( g [ i ] + f [ i ] + 1 ) + n − i n × ( g [ i + 1 ] + f [ i + 1 ] + 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]=ni×(g[i]+f[i]+1)+nni×(g[i+1]+f[i+1]+1)

这里可以这样理解:我在某个时刻已经买到了 n n n种邮票。考虑最后一次花费为 1 1 1,每往前倒推一次操作,花费就增加 1 1 1。现在时光倒流,我从 i i i种邮票买到 n n n种邮票需要 f [ i ] f[i] f[i]步,那么我从 n n n种邮票退回 i i i种邮票也就会需要 f [ i ] f[i] f[i]步。将步数与花费的关系看作 y = x y=x y=x,那么我如果原来在这次买的是已经有的邮票,我这次的花费就是 f [ i ] + 1 f[i]+1 f[i]+1,因为我后面还要买 f [ i ] f[i] f[i]次。如果买的是没有的邮票,这次的花费就是 f [ i + 1 ] + 1 f[i+1]+1 f[i+1]+1,因为我后面还要买 f [ i + 1 ] f[i+1] f[i+1]次。这里的 f [ i ] + 1 , f [ i + 1 ] + 1 f[i]+1,f[i+1]+1 f[i]+1,f[i+1]+1都是这一步的期望花费。

g [ 0 ] g[0] g[0]就是最后的答案。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
double f[maxn],g[maxn],n;
int main(){
	cin>>n;
	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]=g[i+1]+f[i+1]+1.0*f[i]*i/(n-i)+1.0*n/(n-i);
	printf("%.2lf",g[0]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值