洛谷P1291 [SHOI2002]百事世界杯之旅 期望+数学证明

题目描述

“……在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字。只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听,更克赴日韩观看世界杯。还不赶快行动!”
你关上电视,心想:假设有n个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?

输入格式:

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

输出格式:

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

题解

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iomanip>
using namespace std;
typedef long long ll;
ll n;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
struct stu{
    ll a,b;
    stu operator +(const stu&x)const{
        stu res;
        res.b=b*x.b;
        res.a=a*x.b+x.a*b;
        ll g=gcd(res.b,res.a);
        res.a/=g;res.b/=g;
        return res;
    }
}f[40];
signed main(){
    ios::sync_with_stdio(false);
    cin>>n;
    f[1].a=1;f[1].b=1;
    for(ll i=1;i<n;i++){
        stu tmp;tmp.a=n;tmp.b=n-i;
        f[i+1]=f[i]+tmp;
    }
    if(f[n].b==1)cout<<f[n].a<<endl;
    else{
        ll num=0,num2=0;
        ll a=f[n].a,b=f[n].b;
        ll z=a/b;
        while(z){
            num2++;
            z/=10;
        }
        z=a/b;
        a=a%b;
        while(b){
            num++;
            b/=10;
        }
        b=f[n].b;
        for(ll i=1;i<=num2;i++)cout<<" ";
        cout<<a<<endl;
        cout<<z;
        for(ll i=1;i<=num;i++)cout<<"-";
        cout<<endl;
        for(ll i=1;i<=num2;i++)cout<<" ";
        cout<<b<<endl;
    }
}
原文地址:https://www.cnblogs.com/Nan-Cheng/p/9880266.html