zoukankan      html  css  js  c++  java
  • P4550 收集邮票

    P4550 收集邮票

    题目描述

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

    输入格式

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

    输出格式

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

    输入输出样例

    输入 #1
    3
    输出 #1
    21.25


     

    这一道题可咋做?

    顿时懵了

    我们先来想一下这个问题的简化版 由简入繁

    假如一共只有1种邮票 (废话啊) 那买到的概率自然是1/1 肯定能够买到

    (QAQ不就是1嘛)

    假如一共只有2种邮票(事情越来越有意思了)

    如果不考虑两种邮票之间的联系 买到第一种邮票的概率是1/2 第二种也是 1/2

    1+{1*1/2 + 2*1/4 + 3*(1/2)^3 +...+ k*(1/2)^k}   k是正无穷

    化简得1+2=3

    期望做法:

    定义f[i]为差i种买齐时的期望票数

    f[0]=0;//初始定值

    ans=f[n]//答案状态

    拿n=2来举例

    f[1]=1/2*(f[0]+1) + 1/2 *(f[1]+1)

    f[1]=2;

    f[2]=2/2(f[1]+1)=3

    n=3

    f[1]=1/3*(f[0]+1) +2/3*(f[1]+1)  =3

    f[2]=2/3 * (f[1]+1) +1/3*(f[2]+1) =4.5

    f[3]=3/3*(f[2]+1)=5.5

    n

    f[i]=i/n*(f[i-1]+1) +(n-i)/n*(f[i]-1)

    一波移项得

    f[i]=f[i-1]+n/i

    注:以上蒟蒻的异想天开部分的f全部脑补成g

    接下来上我们老师的完整推导过程:

    前方高能!

     

    n=2
    1+ {1*1/2+2*(1/2)^2+3*(1/2)^3+...(k-1)*(1/2)^(k-1)+k*(1/2)^k}
    {}*2={1+2*1/2+3*(1/2)^2+4*(1/2)^3+...k*(1/2)^(k-1)}
    {}={}*2-{}
    =1+1/2+(1/2)^2+(1/2)^3+...+(1/2)^(k-1)-k*(1/2)^k
    =2-(1/2)^(k-1)-k*(1/2)^k
    =2

    ans=3
    定义g[i]为差i种买齐时的期望
    g[0]=0
    n=2
    g[1]=1/2*(g[0]+1)+1/2*(g[1]+1)
    g[1]=g[0]+2=2
    g[2]=2/2*(g[1]+1)=3

    n=3
    g[1]=1/3*(g[0]+1)+2/3*(g[1]+1)
    g[1]=g[0]+3=3
    g[2]=2/3*(g[1]+1)+1/3*(g[2]+1)
    3*g[2]=2*g[1]+g[2]+3
    g[2]=g[1]+1.5=4.5
    g[3]=3/3*(g[2]+1)=5.5

    n
    g[i]=i/n*(g[i-1]+1)+(n-i)/n*(g[i]+1)
    i*g[i]=i*g[i-1]+n
    g[i]=g[i-1]+n/i

    f[i][j]还差i种,这一次买需要j元,到买齐花费的期望
    f[i][j]=i/n*(f[i-1][j+1]+j)+(n-i)/n*(f[i][j+1]+j)

     

    买一张就涨价一元,如果之后还要买g张,那么贡献g*1元
    f[i][j+1]=f[i][j]+g[i]

    f[i][j]=i/n*(f[i-1][j]+g[i-1]+j)+(n-i)/n*(f[i][j]+g[i]+j)
    f[i]=i/n*(f[i-1]+g[i-1]+j)+(n-i)/n*(f[i]+g[i]+j)

    f[i][j]=f[i-1][j]+g[i-1]+(n-i)/i*g[i]+n*j/i

    ans=f[n][1]
    f[i]=f[i-1]+g[i-1]+(n-i)/i*g[i]+n/i

     

     

     

     代码可以继续简化一些哦

    #include<bits/stdc++.h>
    using namespace std;
    //const int maxn=10005;
    //double g[maxn],f[maxn];
    int main()
    {
        int n;
        scanf("%d",&n);
    //    for(int i=1;i<=n;i++)
    //        g[i]=g[i-1]+n*1.0/i;
    //    for(int i=1;i<=n;i++)
    //        f[i]=f[i-1]+g[i-1]+(n-i)*1.0/i*g[i]+n*1.0/i;
    //    printf("%.2lf",f[n]);
        double g=0,f=0;
        for(int i=1;i<=n;i++)
        {
            f=f+g+n*1.0/i;
            g=g+n*1.0/i;
            f=f+(n-i)*1.0/i*g;
        }
        printf("%.2lf",f);
        return 0;
    }
  • 相关阅读:
    Python Requests-学习笔记(9)-错误与异常
    .NET C# 创建WebService服务简单的例子
    10个免费开源的JS音乐播放器插件
    7款高颜值HTML5播放器:让你的音乐有声有色
    Asp.net基于session实现购物车的方法
    ASP.NET用GridView控件实现购物车功能
    jquery鼠标跟随流体吸引特效
    jquery鼠标跟随特效
    JQUERY互动星空粒子背景效果
    jQuery插件库常用前端库引用地址
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/11352934.html
Copyright © 2011-2022 走看看