UVA.1639 Candy (期望 高精度)

来源:互联网 发布:他改变了中国淘宝评论 编辑:程序博客网 时间:2024/06/05 02:32

  • UVA1639 Candy 期望 高精度
    • 题意分析
      • 假设
      • 分析
      • 对数优化
    • 代码总览

UVA.1639 Candy (期望 高精度)

题意分析

有个人有两个都装着n颗糖的箱子,他从其中一个箱子取出一颗糖的概率为p,从另外一个箱子取出糖的概率为1p。有一天他取的时候发现有一个箱子没有糖了,请问另外一个箱子有糖的期望是多少。

假设

我们首先假设现在另外一个箱子还剩下i颗糖果。

分析

既然没有糖了,说明这个人从共取了2ni次糖果,其中取了某个箱子n次,取了另外一个箱子ni次。所以共有Cn2ni种取法,由此可以得到期望公式。(由于最后又取了一下这个箱子,所以应该是n+1次)

i=1nCn2nipn+1(1p)nii

对数优化

由于上式子 pn+1(1p)ni可能非常小,这样的话最后计算会出现问题,所以要想办法进行优化。

优化的办法就是取对数计算。

我们知道: Ckn=n!k!(nk)!, 两边同时取对数后可以得到:

ln(Ckn)=ln(n!)ln(k!)ln((nk)!)

pn+1(1p)ni 也可以如此计算,从而取对数得到:

(n+1)ln(p)+(ni)ln(1p)

具体看代码

代码总览

#include <bits/stdc++.h>#define ld long double#define nmax  2000005using namespace std;ld logpre[nmax * 2];void init(){    for(int i = 1;i<nmax*2;++i){        logpre[i] = logpre[i-1] + log(i);    }}ld get(int n, int k){    return logpre[n] - logpre[k] - logpre[n-k];}double p;int n;int main(){    init();    int kase = 1;    while(scanf("%d %lf",&n,&p) != EOF){        double ans = 0;        long double ans1 = 0,ans2 = 0;        for(int i = 1;i<=n;++i){            ans1 = (get(2*n-i,n) +  (n+1) * log(p) + (n-i) * log(1-p));            ans2 = (get(2*n-i,n) +  (n+1) * log(1-p) + (n-i) * log(p));            ans +=  (long double) i* (exp(ans1) + exp(ans2));        }        printf("Case %d: %lf\n",kase++,ans);    }    return 0;}
原创粉丝点击