....在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;
}