HDU 1099 Lottery (求数学期望)

传送门:

http://acm.hdu.edu.cn/showproblem.php?pid=1099

Lottery

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4319    Accepted Submission(s): 1921


Problem Description
Eddy's company publishes a kind of lottery.This set of lottery which are numbered 1 to n, and a set of one of each is required for a prize .With one number per lottery, how many lottery on average are required to make a complete set of n coupons?
 

 

Input
Input consists of a sequence of lines each containing a single positive integer n, 1<=n<=22, giving the size of the set of coupons.
 

 

Output
For each input line, output the average number of lottery required to collect the complete set of n coupons. If the answer is an integer number, output the number. If the answer is not integer, then output the integer part of the answer followed by a space and then by the proper fraction in the format shown below. The fractional part should be irreducible. There should be no trailing spaces in any line of ouput.
 

 

Sample Input
2 5 17
 

 

Sample Output
3 5 11 -- 12 340463 58 ------ 720720
 

 

Author
eddy
 
题目意思:
 
每次发行n张彩票,要买多少张才能集齐。
 
分析:
假如发行1张,买1次就集齐了。所以买1张。
假如发行2张,第一次买的序号是1,第二次买中剩下那张的概率是1/2,所以要买两张才能买到第二张,所以要买3张才能才能集齐。
假如发行3张,第一次发的序号是1,要买1张,第二次买中剩下的两张之一的概率是2/3,所以要买3/2张,第三次买剩中最后一张的概率是1/3,所以要买3张,所以要买5+1/2张。
假如发行n张,第一次买中没买过的概率是1,第二次是n-1/n,第三次是n-2/n,第n次是1/n,
而对应需要买的张数是第一次买1张,第二次买n/n-1张,第三次买n/n-2,第n次买n张,所以求的是n/n,n/n-1,……1/n的和。
 
所以就是求:n(1+1/2+1/3+......+1/n)
 
举个例子,当n=5时,第一张有用的概率为1,买一张就行了,第二张有用的概率为4/5,所以买5/4张彩票能买上对你有用的,一次类推,sum=1+5/4+5/3+5/2+5/1=11…5/12,
 
需要注意的就是格式问题:(这个很重要,w了几次)
结果是整数的话,直接输出整数
结果不是整数的话,分为两部分输出,一个整数,和一个真分数
格式请参考代码,讲起来太麻烦了。。。
code:
 
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define max_v 25
struct node
{
    LL molecule;//分子
    LL Denominator;//分母
};
LL gcd(LL a,LL b)//最大公约数
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}
LL lcm(LL a,LL b)//最小公倍数
{
    return a/gcd(a,b)*b;
}
LL numlen(LL x)//数字长度
{
    LL c=0;
    while(x)
    {
        x=x/10;
        c++;
    }
    return c;
}
node f(int n)
{
    node p;
    p.molecule=1;
    p.Denominator=1;
    if(n==1)
        return p;
    for(LL i=2;i<=n;i++)
    {
        LL x=lcm(i,p.Denominator);
        p.molecule=p.molecule*(x/p.Denominator)+(x/i);
        p.Denominator=x;
        LL y=gcd(p.Denominator,p.molecule);
        p.Denominator=p.Denominator/y;
        p.molecule=p.molecule/y;
      //  printf("fz=%I64d fm=%I64d 最小公倍数=%I64d\n",p.molecule,p.Denominator,x);
    }
    p.molecule=p.molecule*n;
    LL y=gcd(p.Denominator,p.molecule);
    p.Denominator=p.Denominator/y;
    p.molecule=p.molecule/y;

    return p;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        node p=f(n);
        if(p.molecule%p.Denominator==0)
            printf("%I64d\n",p.molecule/p.Denominator);
        else
        {
            LL x=p.molecule/p.Denominator;
            p.molecule=p.molecule-(x*p.Denominator);
            LL y=gcd(p.Denominator,p.molecule);
            p.Denominator=p.Denominator/y;
            p.molecule=p.molecule/y;

            int l1=numlen(x);
            int l2=numlen(p.Denominator);
            for(int i=0;i<=l1;i++)
                printf(" ");


            printf("%I64d\n",p.molecule);
            printf("%I64d ",x);
            for(int i=1;i<=l2;i++)
                printf("-");
            printf("\n");
            for(int i=0;i<=l1;i++)
                printf(" ");
            printf("%I64d\n",p.Denominator);
        }
    }
    return 0;
}

 

posted @ 2018-07-18 09:19  西*风  阅读(311)  评论(0编辑  收藏  举报