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 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”