洛谷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;
}
}