zoukankan      html  css  js  c++  java
  • 收集邮票(概率dp)

    题目大意

    有n种不同的邮票,皮皮想收集所有种类的邮票。唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且买到的邮票究竟是n种邮票中的哪一种是等概率的,概率均为1/n。但是由于凡凡也很喜欢邮票,所以皮皮购买第k张邮票需要支付k元钱。 现在皮皮手中没有邮票,皮皮想知道自己得到所有种类的邮票需要花费的钱数目的期望。

    输入格式

    • 一行,一个数字N N<=10000

    输出格式

    • 要付出多少钱. 保留二位小数

    算法分析

    • 显然是个期望dp
    • 首先定义dp方程
      设f[i] 表示取到 i 种邮票之后,把其它所有邮票取完的期望次数
      g[i] 表示取到i 种邮票之后,把其它所有邮票取完的期望价格
    • 那么f[i]的转移就是 (f[i] = frac{i}{n}*f[i]) (+) (frac{n-i}{n}) (* f[i+1] + 1) 因为已经选了i种物品 对于选下一种物品 有(frac{i}{n})的概率选到已经已经选过的物品 有(frac{n-i}{n})的概率选到未选到的物品 移项可得 (f[i] = f[i+1]) + (frac{n}{n-i}) 这样我们就得到了关于i 与 i + 1 的线性推关系
    • g[i] 的转移就是 $g[i] = (frac{i}{n} * (g[i] + f[i] + 1)) + (frac{n-i}{n}) * (g[i+1] + f[i+1] + 1) 然后移项可得 g[i] = (frac{i}{n-i}) + (g[i+1] + f[i+1]) + (frac{n}{n-1})
    • 这样我们就可以递推求解了

    Code

    
    
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 10;
    int n;
    double f[maxn],g[maxn];
    
    int main(){
        scanf("%d",&n);
        for(int i=n-1;i >= 0;--i) {
            f[i]=f[i+1]+(1.0*n)/(1.0*(n-i));
            g[i]=(1.0*i)/(1.0*(n-i))*(f[i]+1)+g[i+1]+f[i+1]+1;
        }
        printf("%.2lf
    ",g[0]);
        return 0;
    }
    
    
  • 相关阅读:
    Java中try-catch-finally的一点理解
    子类继承父类的私有属性
    Java中的String[] args
    Java类和类成员的访问权限修饰符
    JAVA中抽象类与接口的区别
    Java C# .net 和 C C++ 跨平台的区别
    Java中的instanceof关键字
    深入理解JAVA的多态性[转]
    Linux文件系统的目录结构
    硬盘分区
  • 原文地址:https://www.cnblogs.com/2004-08-20/p/13518423.html
Copyright © 2011-2022 走看看