bzoj1426 收集邮票(递推+概率期望)

分析:
这道题蛮像的,主要分析转自这里

受到UVa10288启发之后,我们就可以很容易的求出g[i]表示当前有i张邮票,得到n张得期望步数
这里写图片描述
同时我们定义pr(x,i)表示买x次能从i种买到n种的概率
实际pr就是这个:

假设我们现在手里已经有了k图案,令s=k/n,拿一个新的图案需要t次的概率:s^(t-1)*(1-s)

则有
这里写图片描述

设计状态:f[i][j]表示现在有i张不同的邮票,下一次购买需要j+1元,得到n张邮票的期望花费

  • i/n的概率,转移到f[i][j+1],花费是j
  • (n-i)/n的概率,转移到f[i+1][j+1],花费是j

所以状态转移方程显而易见:
f[i][j]=j + f[i][j+1] * i/n + f[i+1][j+1] * (n-i)/n

但是f[i][j]的j是无限的,所以这个递推无法进行,考虑f[i][j]与f[i][j+1]的关系,有


且有


那么有f[i][j]关于f[i+1][j]的状态转移:


再来看看我们的求解,我们只关心f[0][1]是多少,所以,对于j不等于1的情况我们可以忽略

那么定义F[i]表示f[i][1],有


特别的,f[n][1]=0,所以F[n]=0

我们已知F[n]的值与g[0]~g[n]的值,那么我们就可以递推出f[0][1]=F[0]的值,问题到此就可以解决了

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

double g[10010],f[10010];
int n;

int main()
{
    scanf("%d",&n);
    g[n]=0.0;
    for (int i=n-1;i>=0;i--)
        g[i]=g[i+1]+(double)n/(n-i);

    for (int i=n-1;i>=0;i--)
        f[i]=(((f[i+1]+g[i+1])*(double)(n-i)/n)+g[i]*(double)i/n+1.0)*(double)n,f[i]/=(double)n-i;

    printf("%.2lf",f[0]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值