Live2D

【SHOI2002】百事世界杯之旅

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

2002年上海省选的水题

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

所以收集到所有名字的概率就是 \(\sum_{i=1}^{n}\dfrac{n}{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;
}
posted @ 2019-10-06 21:08  tqr06  阅读(166)  评论(0编辑  收藏  举报