【SHOI2002】百事世界杯之旅

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

2002年上海省选的水题

对于任何一个时候,假设已经收集了 \(i\) 种球星名字
那么再买一瓶饮料,收集到不同名字的概率 \(f(i)=\dfrac{n-i}{n}\)

所以收集到所有名字的概率就是 \(n*\sum_{i=1}^{n}\dfrac{1}{i}\)

感觉本题的难点在于输出答案

如果说让你输出期望值(小数)的话,就是真的大水题了
然而题目让你使用一种恶心的方法输出带分数!

所以把分数求出来后,要算出整数部分\(g\),分子部分\(fz\)和分母部分\(fm\)
先输出\(len(g)\)个空格,然后输出\(fz\)(为0则不输出)
第二行输出整数\(g\),输出\(len(fm)\)个下划线
第三行输出\(len(g)\)个空格,再输出分母\(fm\)……
而且还要特判是否有分数部分
反正是很恶心的输出方式啦

代码:

#include<bits/stdc++.h>
#define ll long long
#define fm ans.m
#define fz ans.z
using namespace std;

int n;
struct Fs
{
    ll m,z;
}ans;

int cal(ll x)
{
    int res=0;
    while(x)
    {
        x/=10;
        res++;
    }
    return res;
}

ll gcd(ll a,ll b) {return b? gcd(b,a%b):a;}
ll g;

int main()
{
    fm=1;
    scanf("%d",&n);
    for(register int i=1;i<=n;++i)
    {
        fz=fz*i+fm*n;
        fm*=i;
        g=gcd(fz,fm);
        fz/=g;
        fm/=g;
    }
    g=fz/fm;
    fz%=fm;
    if(!fz)
    {
        printf("%lld\n",g);
        return 0;
    }
    for(register int i=1;i<=cal(g);++i) putchar(' ');
    printf("%lld\n",fz);
    if(g) printf("%lld",g);
    for(register int i=1;i<=cal(fm);++i) putchar('-');puts("");
    for(register int i=1;i<=cal(g);++i) putchar(' ');
    printf("%lld\n",fm);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/tqr06/p/11628460.html