hdu 4465 Candy 数学期望 负二项分布与 数值计算技巧

首先是对于概率的计算,负二项分布: 

  物品A取与不取概率为,p,1-p, 共取 k+r次,最后一次取A ,且取A总次数为 r 次概率为:

    

  则这里两个盒子取也可转换成此模型, 则期望公式为:

  

然后是公式的计算, 这里有两个问题.

  1. 组合数 \binom{ 2n }{ n } 太大,会上溢

  2. p^n 太小会下溢.

对于问题一:

  排列过大,考虑到 y = logx 函数, log(n!) 也不会很大. 又 

  

  令 f(x) = log( x! ),则有

  

  预处理出 函数f() 就可以 O(1)求出 log( \binom{n}{m} )了. 然后 再求个 exp( x ) 就可以还原了.

对于问题二:

  p^x 值过小.  log( p^x ) = x * logp  这样值就在可控范围内. 同样一次 exp( x ) 就可以还原

View Code
#include<cstdio>
#include<cstdlib>
#include<cmath>
const int N = (int)5e5+10;
int n;
double p, f[N];

double C(int n, int m){
    return f[n] - f[m] - f[n-m];
}

int main(){
    int Case = 1;
    f[0] = 0;
    for(int i = 1; i <= 400000; i++) f[i] = f[i-1]+log(1.*i);

    while( scanf("%d %lf", &n,&p) != EOF){
        double res = 0;    
        double p1 = log(p), p2 = log(1-p);
        for(int i = 0; i <= n; i++){
    //        res += 1.*i*c[n+n-i]*(p1[n+1]*p2[n-i]+p1[n-i]*p2[n+1]);    
            res += 1.*i*(
                exp(C(n+n-i,n) + (n+1)*p1 + (n-i)*p2 )    
            +exp( C(n+n-i,n) + (n+1)*p2 + (n-i)*p1 )    
                    );    
        }
        printf("Case %d: %.6f\n", Case++, res );    
    }
    return 0;
}

 

posted @ 2013-04-24 13:48  yefeng1627  阅读(1248)  评论(0编辑  收藏  举报

Launch CodeCogs Equation Editor