/*转载请注明出处:乄心-小黄豆http://blog.csdn.net/wuxinxiaohuangdou*/
我也是看别人的解释才懂得!
/*转注释*/
1.题意解释:意思是有n种彩票,你要想集齐这所有的n种,需要买多少张彩票(就像我们小时候吃小当家集108个水浒英雄的卡片一样,要买多少袋?当然我们吃小当家的时候108种卡片可不是均匀出现的,呵呵,跑题了).
2.如果有n种,那么我们要求的结果就是n/n + n/n-1 + n/n-2 +...+ n/2 + n/1 ,即n*(1/n + 1/n-1 +...+ 1/2 +1/1)
原理: 我们要集齐n种不同的彩票,
买第一张任意,概率为n/n,买第二张就需要和第一张不同,即剩下的n-1种里哪种都可以,成功的概率是n-1/n...如果我们已经集齐了n-1种,再买彩票我们希望买到最后一种,由于是均匀分布的,所以买到最后一种彩票的概率是1/n.那么从期望的角度来说我们需要买n张,才能买到(当然我们就算买n张也不一定就能买到,也可能买1张就买到了最后一种,完全是从数学角度!!! 概率角度!!!),同理,当我们拥有一半种类的彩票时,再买一张彩票不重复的概率是(n/2)/n,即1/2,也就说买2张,就会再得到一种不重复的
所以一种彩票也没有时,只需买1张,即n/n,如果已经有了5张,那么买n/(n-5)张就可以再买到一张不重复的,如果我们已经集了n-1种,我们需要再买n张,才能期望得到最后一种彩票,所以需要买的彩票总数为n/n + n/n-1 + n/n-2 +...+ n/2 + n/1;
3.代码细节: 明白了题意,就是在求n*(1/n + 1/n-1 +...+ 1/2 +1/1),由于题目要求的表达方式比较特殊,整个解题过程基本都是在处理分数的通分了,如果让用小数表示那这个题就几行代码就结束了.由于分子会溢出int的范围,用到了_int64.
/*也可以求*/
不同种类彩票的总数!比如:n=3(3种概率彩票);不同种类的有 1,1/2,1/3;那么要有概率为1的彩票3张,1/2的1.5张,1/3的一张!
总数:总共要5.5张彩票!
#include<iostream>
#include<cstdio>
using namespace std;
__int64 GCD(__int64 a,__int64 b) //辗转相除法 (a,b不用判断大小。)
{
if(b==0) return a;
else return GCD(b,a%b);
}
void format1(__int64 x)
{
__int64 i;
for(i=1;x!=0;i++)
{
x/=10;
}
while(i--) cout<<" ";
}
void format2(__int64 x)
{
__int64 i;
for(i=1;x!=0;i++)
{
x/=10;
}
i--;
while(i--) cout<<"-";
}
__int64 main()
{
__int64 nume,deno,inter,gcd,lcm;//分子,分母,整数位,最大公约数,最小公倍数。
int n;
while(cin>>n)
{
nume=1;
deno=n;
for(__int64 i=n-1;i>=1;i--) //模拟 1/n + 1/(n-1) + 1/(n-2) + ......+ 1/1
{
gcd=GCD(deno,i); //先计算最大公约数
lcm=(deno*i)/gcd; //最小公倍数==两个数乘积 /最大公约数。
nume=(lcm/deno)*nume+lcm/i; //分子更新
deno=lcm;//分母更新
}
nume=nume*n; //分子*n变成假分式。
gcd=GCD(nume,deno);//求分子分母最大公约数
nume=nume/gcd;
deno=deno/gcd;//分子分母同除以最大公约数化到最简假分式。
inter=nume/deno;//得到整数位
nume=nume%deno;//得到真分式的分子。
if(deno==1) printf("%I64d\n",inter);//如果没有分数则直接输出 整数!
else //否则按格式输出!
{
format1(inter+1); //输出空行
printf("%I64d\n%I64d ",nume,inter);
format2(deno);//划横线 输出横线之后要换行
cout<<endl;
format1(inter+1);//输出空行
printf("%I64d\n",deno);
}
}
return 0;
}