码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 4465 Candy->概率-数学期望-排列组合

时间:2015-06-09 10:00:26      阅读:542      评论:0      收藏:0      [点我收藏+]

标签:c   c++   acm   算法   编程   

题意:有两个箱子,里面各放有糖n个,每天从两个之中任取一颗糖,突然有一天小孩取糖时发现一个盒子里空了,问另一个盒子里面现在有多少糖(求期望值)?

#include<iostream>
#include<cmath>
using namespace std;

double F[400008];

double C_N_M(int n,int m)
{
	return F[n]-F[m]-F[n-m];
}

void Init()
{
	int i;

	F[0]=0;
	for(i=1;i<=400006;i++)
		F[i]=F[i-1]+log(i*1.0);
}

double sovle(int n,double p)
{
	double sum;
	int k;

	for(sum=0,k=0;k<=n-1;k++)
		sum+=(n-k)*(exp((C_N_M(n+k,k))+(n+1)*log(p)+k*log(1-p))+
		    exp((C_N_M(n+k,k))+(n+1)*log(1-p)+k*log(p)));
	return sum;
}

int main()
{
	double p;
	int n,t=0;

	Init();
	while(cin>>n>>p)
	{
		printf("Case %d: %.6f\n",++t,sovle(n,p));
	}
	return 0;
}


参考自:http://blog.csdn.net/sylg_li/article/details/8208514http://www.tuicool.com/articles/zInIja

先说说我做这个题走过的的误区,我错误的以为题目里面说的那个the other box指的是取得概率为1-p那个,最后看了有一个解题报告的公式才知道算的是两个的期望值之和。这个题期望的公式好推,就是算排列组合的时候可能不知道问么算,取log()(这个是数学里面的ln可别以为是)饥渴,还原的时候用exp()。还有一点,第一个箱子为空时仍然要取一次糖,因为取不出来的时候才知道糖完了。

技术分享

这个地方也要注意,为什么是C(n+k,k)而不是C(n+k+1,k)?k表示的是the other box取的糖的数目,我们在第一个箱子取了n+1次糖,可是那次取空时并没有取到糖果,所以我们算期望值时的概率还是要用C(n+k,k)

技术分享

计算组合数最大的困难在于数据的溢出,对于大于150的整数n求阶乘很容易超出double类型的范围,那么当C(n,m)中的n=200时,直接用组合公式计算基本就无望了。另外一个难点就是效率。

    对于第一个数据溢出的问题,可以这样解决。因为组合数公式为:
    C(n,m) = n!/(m!(n-m)!)

    为了避免直接计算n的阶乘,对公式两边取对数,于是得到:
    ln(C(n,m)) = ln(n!)-ln(m!)-ln((n-m)!)

    进一步化简得到:

    技术分享

    这样我们就把连乘转换为了连加,因为ln(n)总是很小的,所以上式很难出现数据溢出。

    为了解决第二个效率的问题,我们对上式再做一步化简。上式已经把连乘法变成了求和的线性运算,也就是说,上式已经极大地简化了计算的复杂度,但是还可以进一步优化。从上式中,我们很容易看出右边的3项必然存在重复的部分。现在我们把右边第一项拆成两部分:

    技术分享

    这样,上式右边第一项就可以被抵消掉,于是得到:

    技术分享

    上式直接减少了2m次对数计算及求和运算。但是这个公式还可以优化。对于上面公式里的求和,当m<n/2时,n-m是一个很大的数,但是当m>n/2时,n-m就会小很多。我们知道:
    C(n,m) = C(n,n-m)

    那么通过这个公式,我们可以把小于n/2的m变为大于n/2的n-m再进行计算,结果是一样的,但是却能减少计算量。

    当计算出ln(C(n,m))后,只需要取自然对数,就可以得到组合数:
    C(n,m) = exp(ln(C(n,m)))

    这样就完成了组合数的计算。

    用这种方法计算组合数,如果只计算ln(C(n,m))的话,n可以取到整型数据的极限值65535,


HDU ACM 4465 Candy->概率-数学期望-排列组合

标签:c   c++   acm   算法   编程   

原文地址:http://blog.csdn.net/a809146548/article/details/46420017

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!