P1291 百事世界杯之旅

题目描述

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

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

输入输出格式

输入格式:

 

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

 

输出格式:

 

输出凑齐所有的名字平均需要买的饮料瓶数。如果是一个整数,则直接输出,否则应该直接按照分数格式输出,例如五又二十分之三应该输出为(复制到记事本):

3 5-- 20 第一行是分数部分的分子,第二行首先是整数部分,然后是由减号组成的分数线,第三行是分母。减号的个数应等于分母的为数。分子和分母的首位都与第一个减号对齐。

分数必须是不可约的。

 

输入输出样例

输入样例#1:
2
输出样例#1:
3
/*
    当有k个人的时候,抽到下一个的概率是n-k/n  所以平均需要n/n-k瓶才能买到下一个
    所以ANS=n(1/1+1/2+1/3+....1/n)
    这里可以用分数直接计算
*/
#include<iostream>
#include<cstdio>
using namespace std;
long long mul=1,n,sum;
long long GCD(long long x,long long y){
    if(y==0)return x;
    return GCD(y,x%y);
}
int main(){
    //freopen("Cola.txt","r",stdin);
    cin>>n;
    for(long long i=1;i<=n;i++)
    {
        long long tmp1=i/GCD(i,mul),tmp2=mul/GCD(i,mul);
        mul*=tmp1;//分母 
        sum=sum*tmp1+n*tmp2;//分子 
        int r=GCD(sum,mul);
        sum/=r;mul/=r;
    }
    if(mul==1){
        cout<<sum;
        return 0;
    }
    if(sum<mul){
        cout<<sum;
        long long len=0;
        long long cp=mul;
        while(cp){
            len++;
            cp/=10;
        }
        for(long long i=1;i<=cp;i++)printf("-");printf("\n");
        cout<<mul;
        return 0;
    }
    if(sum>mul){
        long long len1=0,len2=0;
        long long x=sum/mul;
        sum%=mul;
        long long cp1=x,cp2=mul;
        while(cp1){//整数部分长度 
            len1++;
            cp1/=10;
        }
        while(cp2){
            len2++;
            cp2/=10;
        }
        for(long long i=1;i<=len1;i++)printf(" ");
        cout<<sum<<endl;
        cout<<x;
        for(long long i=1;i<=len2;i++)printf("-");printf("\n");
        for(long long i=1;i<=len1;i++)printf(" ");
        cout<<mul;
    }
}