zoukankan      html  css  js  c++  java
  • UVa 1639

    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4514

    题意:

    有两个盒子各有n(1≤n≤2e5)个糖,每天随机选一个(概率分别为p,1-p),然后吃一颗糖。
    直到有一天,打开盒子一看,没糖了!输入n,p,求此时另一个盒子里糖的个数的数学期望。

    分析:

    根据期望的定义,不妨设最后打开第1个盒子,此时第2个盒子有i颗,则这之前打开过n+(n-i)次盒子,
    其中有n次取的是盒子1,其余n-i次取的盒子2,概率为C(2n-i,n)(p^(n+1))((1-p)^(n-i))。
    注意p的指数是n+1,因为除了前面打开过n次盒子1之外,最后又打开了一次。
    这个概率表达式在数学上是正确的,但是用计算机计算时需要小心:
    n可能高达20万,因此C(2n-i,n)可能非常大,而(p^(n+1))和((1-p)^(n-i))却非常接近0。
    如果分别计算这3项再乘起来,会损失很多精度。
    一种处理方式是利用对数,设v1(i) = ln(C(2n-i,n)) + (n+1)ln(p) + (n-i)ln(1-p),
    则“最后打开第1个盒子”对应的数学期望为e^v1(i)。
    同理,当最后打开的是第2个盒子,对数为v2(i) = ln(C(2n-i,n)) + (n+1)ln(1-p) + (n-i)ln(p),概率为e^v2(i)。
    根据数学期望的定义,最终答案为sum{i(e^v1(i)+e^v2(i))}。

    代码:

     1 #include <cstdio>
     2 #include <cmath>
     3 
     4 const int UP = 2e5 * 2 + 5;
     5 long double logF[UP];
     6 
     7 // C(n,m) = n!/(m!(n-m)!)
     8 long double logC(int n, int m) {
     9     return logF[n] - logF[m] - logF[n-m];
    10 }
    11 
    12 double solve(int n, double p) {
    13     double ans = 0;
    14     for(int i = 0; i <= n; i++) {
    15         long double c = logC(n+n-i, n);
    16         long double v1 = c + (n+1)*log(p) + (n-i)*log(1-p);
    17         long double v2 = c + (n+1)*log(1-p) + (n-i)*log(p);
    18         ans += i * (exp(v1) + exp(v2));
    19     }
    20     return ans;
    21 }
    22 
    23 int main() {
    24     logF[0] = 0;
    25     for(int i = 1; i < UP; i++) logF[i] = logF[i-1] + log(i);
    26     int n;
    27     double p;
    28     for(int cases = 1; ~scanf("%d%lf", &n, &p); cases++) {
    29         printf("Case %d: %.6f
    ", cases, solve(n, p));
    30     }
    31     return 0;
    32 }
  • 相关阅读:
    九,WPF资源
    八,WPF 命令
    七,WPF的元素绑定
    六,WPF的Application类
    五,控件
    四,路由事件
    三,依赖项属性
    二,WPF的布局
    一,XAML基础
    压缩解压缩字符串
  • 原文地址:https://www.cnblogs.com/hkxy125/p/9559936.html
Copyright © 2011-2022 走看看