HDU4465 Candy
Posted Blogggggg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于HDU4465 Candy的主要内容,如果未能解决你的问题,请参考以下文章
HDU 5654 xiaoxin and his watermelon candy 离线树状数组
hdu 5380 Travel with candy(双端队列)
dp hdu5653 xiaoxin and his watermelon candy