题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4465
知识点: 概率和期望
题目大意:
懒小孩有 2 个盒子,每个盒子里面有 (n (1 le n le 2 imes 10^5)) 颗糖,懒小孩每天有 (p (0 le p le 1)) 的概率打开第一个盒子,当然,打开另一个盒子的概率就是 (p-1) 了。问当某一天他打开一个盒子,发现其中没有糖,然后再去打开另一个盒子的时候,该盒子中的糖的期望值是多少?
解题思路:
设小孩在第 (i (i: n+1 o 2n+1)) 天发现一个盒子里面没有糖,此时有两种情况:第一个盒子没有糖,则第二个盒子里面糖数的期望值为 (C_{i-1}^{n} underline{p^{n+1}} (1-p)^{i-1-n} (2n-i+1)) (注意划线处是 (p^{n+1}) 而不是 (p^n) ,因为第一个盒子一共被选了 (n+1) 次);同理,第二个盒子没有糖时,第一个盒子里面糖数的期望值为 (C_{i-1}^{n} p^{i-1-n} (1-p)^{n+1} (2n-i+1)) .
公式明确了,而且我们不难发现:第 (i+1) 天的期望值可以由第 (i) 天推得,但现在的问题是:当 n 很大时,组合数会大得爆 (long long),但概率在 N 多次方下会小成 0 。于是我们只好用 (log())先取这两者的对数,然后先在对数的状态下将二者加起来,然后再用 (exp()) 处理他们的和,这样得到的结果也相当于两者相乘的积。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 5 using namespace std; 6 7 int main() 8 { 9 int n,kase=1; 10 double p; 11 while(scanf("%d%lf",&n,&p)==2){ 12 double C=log(1.0); 13 double p1=0,p2=0; //p1 用于求第一种情况,而 p2 用于求第二种情况 14 for(int i=0;i<n+1;i++) p1+=log(p),p2+=log(1-p); 15 double ans=0; 16 for(int i=n+1;i<=2*n+1;i++){ 17 ans=ans+(exp(C+p1)+exp(C+p2))*(2*(double)n-i+1); 18 C+=log((double)i/((double)i-n)); 19 p1+=log(1-p),p2+=log(p); 20 } 21 printf("Case %d: %.6lf ",kase++,ans); 22 } 23 return 0; 24 }