首页 > 其他 > 详细

Uva1639(概率期望/对数处理避免丢失精度)

时间:2018-08-21 23:58:25      阅读:249      评论:0      收藏:0      [点我收藏+]

Uva1639

题意:

有两个盒子各有n个糖果(n<=200000),每天随机选择一个:选第一个盒子的概率是p(0 ≤ p ≤ 1),第二个盒子的概率为1-p,然后吃掉其中的一颗。直到有一天,随机选择一个盒子打开一看,没糖了!现在请你计算另一个盒子里剩下的糖果数量的期望值。

解法:

我们假设到第n天的时候取得是第1个盒子的糖,此时第2个盒子有i颗糖,则在此之前打开了n+(n-i)次盒子, 其中n次打开了第一个盒子,(n-i)次打开了第二个盒子,则概率是C(2n-i,n)*p^(n+1)*(1-p)^n-i。

由于n高达20w,所以二次项系数会非常大,而后面的概率会非常小,所以如果直接计算会爆精度,所以这里我们用求对数的方法进行计算

 1 #include<iostream>
 2 #include<cmath>
 3 using namespace std;
 4 typedef long double lb;
 5 const int maxn = 2e5 + 5;
 6 long double logF[2 * maxn + 66];
 7 
 8 void generate() {
 9     //预处理出n!的log值
10     logF[0] = 0;
11     for (int i = 1; i <= maxn; i++)
12         logF[i] = logF[i - 1] + log(i);
13 }
14 // C(n,m) = n!/(m!(n-m)!)
15 long double logC(int n, int m) {
16     return logF[n] - logF[m] - logF[n - m];
17 }
18 
19 int main() {
20     int n; double p;
21     generate();
22     int kase = 1;
23     while (scanf("%d%lf", &n, &p)!=EOF) {
24         double ans = 0;
25         for (int i = 0; i <= n; i++) {
26             long double v1 = logC(2 * n - i, n) + (n + 1)*log(p) + (n - i)*log(1 - p);
27             long double v2 = logC(2 * n - i, n) + (n + 1)*log(1 - p) + (n - i)*log(p);
28             ans += (i*(exp(v1) + exp(v2)));
29         }
30         printf("Case %d: %.6lf\n", kase++, ans);
31     }
32     return 0;
33 }

 

Uva1639(概率期望/对数处理避免丢失精度)

原文:https://www.cnblogs.com/romaLzhih/p/9515177.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!