UVA.1639 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  2000005
using 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值