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

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

时间:2018-08-22 00:12:53      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:main   n+1   col   std   style   code   uva   scan   amp   

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(概率期望/对数处理避免丢失精度)

标签:main   n+1   col   std   style   code   uva   scan   amp   

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

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