[FROM WOJ]#1468 百事世界杯之旅

本文探讨了一道有趣的概率问题,即在每种饮料瓶盖上都有一个随机的球星名字的情况下,为了集齐n个不同的名字,平均需要购买多少瓶饮料。文章提供了问题的数学模型及解决思路。

#1468 百事世界杯之旅

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

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

输出
如果输出是整数,那么直接输出一个整数
如果有分数,分数必须不可再约。 分3行打印 第一行是分子,前面有整数部分的位数+1个空格
第二行是整数部分+1个空格+分母位数个、‘-’
第三行是分母,前面有整数部分的位数+1个空格

样例输入
2

样例输出
3

SOL
我们假设当前已经有k个球星,那么我们要开出第k+1个球星的期望为n/n-k,于是开出n个球星的期望为
n∗∑i=1n1/in*\sum_{i=1}^{n}1/ini=1n1/i
于是这道题最难的就是输出带分数(还要最简,丧心病狂!!!……
经过思考,可以考虑维护每个值的整数部分,分数部分通分加起来,分数部分的和的整数部分加到当前统计的整数部分里。
完了。
代码太丑,望诸位神仙见谅!

代码:

#include<bits/stdc++.h>
#define int long long
#define N 100005
using namespace std;
inline int rd(){
	static char ch=0;int register data=0,w=1;
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(isdigit(ch))data=(data<<1)+(data<<3)+ch-'0',ch=getchar();
	return data*w;
}
int z,n,a,b=1;//z+(a/b)
inline int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);}
signed main(){
	n=rd();
	for(int register i=1;i<=n;i++)z+=n/i,b*=i/gcd(b,i);
	for(int register i=1;i<=n;i++)a+=n*b/i%b;
	int register num=0,x=gcd(a,b);
	a/=x,b/=x;
	z+=a/b;a%=b;
	if(!a){cout<<z;exit(0);}
	x=z;while(x){x/=10;num++;}if(num)num++;
	while(num--)putchar(' ');cout<<a<<endl;
	if(z)cout<<z;putchar(' ');
	num=0;x=b;while(x){x/=10;num++;}while(num--)putchar('-');cout<<endl;
	num=0;x=z;while(x){x/=10;num++;}if(num)num++;
	while(num--)putchar(' ');cout<<b;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值