hdu1099 Lottery

1.题意解释:意思是有n种彩票,你要想集齐这所有的n种,需要买多少张彩票

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.

以上摘自http://hi.baidu.com/zf2650/blog/item/1525a21f5a15cbff1ad57667.html

下面是我的代码:

//n*(1/1+1/2+1/3+...+1/n)
#include<iostream>
#include<algorithm>
using namespace std;


__int64 gcd(__int64 a,__int64 b)
{
	if(b==0)
		return a;
	else
		return gcd(b,a%b);
}

__int64 lcm(__int64 a,__int64 b)
{
	return a/gcd(a,b)*b;
}

__int64 numlen(__int64 n)
{
	__int64 l=0;
	while(n)
	{
		n=n/10;
		l++;
	}
	return l;
}

int main()
{
	__int64 n,son,mother,g,d,i;
	while(scanf("%I64d",&n)!=EOF)
	{
		mother=1,son=0;
		for(i=1;i<=n;i++)
			mother=lcm(mother,i);
		for(i=1;i<=n;i++)
			son=son+mother/i;
		son=son*n;
		g=gcd(mother,son);
		son=son/g;
		mother=mother/g;
		d=son/mother;
		son=son%mother;
		if(son==0)
		{
			printf("%d\n",d);
			continue;
		}
		__int64 l1=numlen(d);
		__int64 l2=numlen(mother);
		for(i=0;i<=l1;i++)
			printf(" ");
		printf("%I64d\n",son);
		printf("%I64d ",d);
		for(i=1;i<=l2;i++)
			printf("-");
		printf("\n");
		for(i=0;i<=l1;i++)
			printf(" ");
		printf("%I64d\n",mother);
	}
	return 0;
}

 



posted @ 2011-11-13 10:22  枕边梦  阅读(690)  评论(0编辑  收藏  举报