您的位置:首页 > 其它

Hdu 4465 Candy (快速排列组合+概率)

2015-08-28 21:15 375 查看
题目链接:

  Hdu 4465 Candy

题目描述:

  有两个箱子,每个箱子有n颗糖果,抽中第一个箱子的概率为p,抽中另一个箱子的概率为1-p。每次选择一个箱子,有糖果就拿走一颗,没有就换另外一个箱子。问换箱子的时候,另外一个箱子中剩下糖果的期望值。

解题思路:

  注意题目描述,其中任意一个箱子没有糖果,另一个箱子中剩下糖果个数的期望,而不是第一个箱子没有糖果。不是把其中一个箱子取空时,另一个箱子剩下糖果的期望,而是其中一个箱子取空再换另外一个箱子时,这个箱子的期望。

  可以根据期望性质画出公式:ans = (n-i) * C(n+i,n) * (p^(n+1)*(1-p)^i + (1-p)^(n+1)*p^i) (0<=i<=n);新的问题又来了,C(n+i,n)由于n的原因可能会向上溢出,而p^(n+1)又可能会很小,然后向下溢出。可以分别对他们进行取log,log(C(n+i,n))范围变小,log(p^(n+1))变成负数,方便保存。

/*
******未处理精度的代码,推论严密美丽也无卵用********
期望公式Ε=∑ P * N    p为概率 n为数量
P=p*C(n,m)*p^n*(1-p)^(m-n)
c(m,n)=c(m-1,n)*m/(m-n)
概率
m=0      p^(n+1)
m=1      p^(n+1)q
m=2      p^(n+1)q^2
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;

int main ()
{
int t, i, l = 1;
double ans, p1, p2, res1, res2;
while (scanf ("%d %lf", &t, &p1) != EOF)
{
p2 = (1.0 - p1);
res1 = t * p1;
ans = 1;
res2 = t * p2;
for (int i=1; i<=t; i++)
{
ans *= p1 * p2 * (t + i) / i;
res1 += ans * (t - i);
res1 *= p1;
res2 += ans * (t - i);
res2 *= p2;
}
printf ("Case %d: %6lf\n", l++, res1+res2);
}
return 0;
}


/*
取log处理精度问题,exp还原结果
*/
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 400005;
double Logf[maxn];
void init ()
{
Logf[0] = 0;
for (int i=1; i<maxn; i++)
Logf[i] = Logf[i-1] + log(i*1.0);
}
double C (int m, int n)
{
return Logf[m] - Logf
- Logf[m-n];
}
int main ()
{
int n, cas = 1;
double p1, p2, ans;
init ();
while (scanf ("%d %lf", &n, &p1) != EOF)
{
ans = 0;
p2 = 1.0 - p1;
p1 = log(p1);
p2 = log(p2);
for (int i=0; i<n; i++)
{
ans += ((n-i) * exp(C(n+i, n) + (n+1)*p1 + i*p2));
ans += ((n-i) * exp(C(n+i, n) + (n+1)*p2 + i*p1));
}
printf ("Case %d: %f\n", cas++, ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: