HDU4465 Candy

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4465

知识点:  概率和期望

题目大意:

  懒小孩有 2 个盒子,每个盒子里面有 \(n (1 \le n \le 2 \times 10^5)\) 颗糖,懒小孩每天有 \(p (0 \le p \le 1)\) 的概率打开第一个盒子,当然,打开另一个盒子的概率就是 \(p-1\) 了。问当某一天他打开一个盒子,发现其中没有糖,然后再去打开另一个盒子的时候,该盒子中的糖的期望值是多少?

解题思路:

  设小孩在第 \(i  (i: n+1 \to 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\n",kase++,ans);
22     }
23     return 0;
24 }

 

posted @ 2017-11-20 23:32  Blogggggg  阅读(235)  评论(0编辑  收藏  举报