【题目】
题目描述:
“……在 年 月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字。只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听,更克赴日韩观看世界杯。还不赶快行动!”
你关上电视,心想:假设有 个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?
输入格式:
整数 ( ≤ ≤ ),表示不同球星名字的个数。
输出格式:
输出凑齐所有的名字平均需要买的饮料瓶数。如果是一个整数,则直接输出,否则应该直接按照分数格式输出,例如五又二十分之三应该输出为 ,第一行是分数部分的分子,第二行首先是整数部分,然后是由减号组成的分数线,第三行是分母。减号的个数应等于分母的位数。分子和分母的首位都与第一个减号对齐。
分数必须是不可约的。
样例数据:
输入
2
输出
3
【分析】
话说这道题输出好迷啊
首先要有一个结论:假设现在已经收集了 个球星的名字,那么要使球星的名字达到 ,平均需要买 瓶饮料
感性理解一下吧(反正我也不会证),现在已经有
个球星的名字,下一次买饮料买到新的球星名字的概率就是
,那平均买
次就可以买到新的了
那么答案就很好算了,就是 (提一个 就是调和级数了)
由于数据规模并不大,所以直接开 进行计算就可以了,还要注意边求和边约分
再次吐槽一下输出,太鬼畜了。。。
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long lcm(long long x,long long y) {return x*y/__gcd(x,y);}
void calc(long long &mol,long long &den,long long x,long long y)
{
long long l=lcm(den,y);
mol*=l/den,x*=l/y;mol+=x,den=l;
long long g=__gcd(mol,den);
mol/=g,den/=g;
}
int len(long long x)
{
int ans=0;
while(x!=0) ans++,x/=10;
return ans;
}
int main()
{
int n,i;
scanf("%d",&n);
long long mol=n,den=1;
for(i=2;i<=n;++i)
calc(mol,den,n,i);
if(mol%den==0) printf("%lld",mol);
else
{
int num1=len(den);
int num2=len(mol/den);
for(i=1;i<=num2;++i) printf(" ");
printf("%lld\n%lld",mol%den,mol/den);
for(i=1;i<=num1;++i) printf("-");
printf("\n");
for(i=1;i<=num2;++i) printf(" ");
printf("%lld",den);
}
return 0;
}