zoukankan      html  css  js  c++  java
  • 洛谷 P1291 [SHOI2002]百事世界杯之旅 解题报告

    P1291 [SHOI2002]百事世界杯之旅

    题目描述

    “……在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字。只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听,更克赴日韩观看世界杯。还不赶快行动!”

    你关上电视,心想:假设有n个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?

    输入输出格式

    输入格式:

    整数(n)(2≤n≤33),表示不同球星名字的个数。

    输出格式:

    输出凑齐所有的名字平均需要买的饮料瓶数。如果是一个整数,则直接输出,否则应该直接按照分数格式输出,例如五又二十分之三应该输出为(复制到记事本): (5 frac{3}{20})第一行是分数部分的分子,第二行首先是整数部分,然后是由减号组成的分数线,第三行是分母。减号的个数应等于分母的为数。分子和分母的首位都与第一个减号对齐。

    分数必须是不可约的。


    我确信洛谷和网上的题解大部分都是错的,少部分是对的的也并没有说清楚。

    比如说这个题极限的思想,我没有看到一个提出来的。

    首先得明白一点,当已经买到所有的名字以后,是不需要再买的。针对于子问题也这样想。

    从两个方面分别具体说说这个题目。

    一、对每一步暴力极限求解。

    (f[i])表示已经买到(i)个球星的期望购买次数。

    我们由(f[i])(f[i+1])

    下一次购买可以买到不同球星的概率是(frac{n-i}{n})

    下两次购买可以买到不同球星的概率是(frac{i}{n} imes frac{n-i}{n}) 注意到这时第一次买到的情况已经忽略了

    ...

    (k)次购买可以买到不同球星的概率是((frac{i}{n})^{k-1} imes frac{n-i}{n})

    假设第(k)次就是正无穷次

    则此步的期望即为

    (E=1 imes frac{n-i}{n}+2 imes frac{i}{n} imes frac{n-i}{n}+3 imes (frac{i}{n})^2 imes frac{n-i}{n}+...+k imes (frac{i}{n})^{k-1} imes frac{n-i}{n})

    则有

    (frac{i}{n} imes E=1 imes frac{i}{n} imes frac{n-i}{n}+2 imes (frac{i}{n})^2 imes frac{n-i}{n}+3 imes (frac{i}{n})^3 imes frac{n-i}{n}+...+k imes (frac{i}{n})^k imes frac{n-i}{n})

    错位相减

    (Eapprox 1+frac{i}{n}+(frac{i}{n})^2+...(frac{i}{n})^{k-1})

    此步中采用极限的思想丢了一些(0)的项,用“(approx)”表示采用极限思想,实际上极限是准确值,不需要“(approx)”,此处只是为了标示,下同。

    由等比数列公式

    (E=1+frac{frac{i}{n}-(frac{i}{n})^k}{frac{n-i}{n}})

    (approx frac{n}{n-i})

    所以我们得出

    (f[i+1]=f[i]+frac{n}{n-i})

    (f[n]=n imes (frac{1}{1}+frac{1}{2}+...+frac{1}{n}))

    二、神奇的自己推自己的方法

    同样令(f[i])表示已经买到(i)个球星的期望购买次数。

    如果从上一个推过来,为

    (f[i]+=(f[i-1]+1) imes frac{n-(i-1)}{n})

    如果从当前推过来,为

    (f[i]+=(f[i]+1) imes frac{i}{n})

    发现概率之和并不等于1,也就是说,这样写是有问题的。

    从上一个推过来肯定没问题,我们考虑从当前推当前的意义。

    “买了一个,买的是自己有的的概率”

    然而我们考虑最开始说的一句话

    “当已经买到所有的名字以后,是不需要再买的。”

    也就是说,我们这样写可能把自己买了很多遍,而事实上是并不需要再买的。

    于是我们修改一下意义

    为“买了一个,买的是自己有的且不是自己的概率”

    则推过来就是

    (f[i]+=(f[i]+1) imes frac{i-1}{n})

    那我们这个什么时候买呢?

    极限的思想,在最后买时,对期望的影响是微乎其微的

    把这两项加起来并化简

    就得到了

    (f[i]=f[i-1]+frac{n}{n-i+1})

    和上一个方法的结果是一样的

    关于合并两个值并不是一样的(f[i]),用的也是极限的思想


    Code:

    #include <cstdio>
    #define ll long long
    ll gcd(ll a,ll b)
    {
        return b?gcd(b,a%b):a;
    }
    int cal(ll a)
    {
        int cnt=0;
        while(a)
            cnt++,a/=10;
        return cnt;
    }
    struct node
    {
        ll p,q;
        node(){}
        node friend operator +(node n1,node n2)
        {
            node n3;
            n3.p=n1.p*n2.p;
            n3.q=n1.p*n2.q+n1.q*n2.p;
            ll d=gcd(n3.p,n3.q);
            n3.p/=d,n3.q/=d;
            return n3;
        }
        node(int q,int p)
        {
            this->p=p;
            this->q=q;
        }
    };
    int main()
    {
        ll n;
        scanf("%lld",&n);
        node f(1,1);
        for(int i=2;i<=n;i++)
        {
            node t(1,i);
            f=f+t;
        }
        f.q*=n;
        ll d=gcd(f.q,f.p);
        f.p/=d,f.q/=d;
        if(f.p==1)
        {
            printf("%lld
    ",f.q);
            return 0;
        }
        ll Int=f.q/f.p;
        int len=cal(Int);
        for(int i=1;i<=len;i++)
            printf(" ");
        printf("%lld
    %lld",f.q%f.p,Int);
        int len2=cal(f.p);
        for(int i=1;i<=len2;i++)
            printf("-");
        printf("
    ");
        for(int i=1;i<=len;i++)
            printf(" ");
        printf("%lld
    ",f.p);
        return 0;
    }
    
    

    2018.7.27

  • 相关阅读:
    通过jsonp解决ajax的跨域请求问题
    为php安装redis扩展模块并测试
    浅谈使用 PHP 进行手机 APP 开发(API 接口开发)(转)
    touch事件记录
    jquery mobile 问题
    background总结,转自http://www.daqianduan.com/3302.html
    博客收集
    css3 border-radius 总结
    css3 box-shadow 总结
    angular 重置表单
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9376392.html
Copyright © 2011-2022 走看看