HDU 4465 Candy 概率期望值的对数优化
2017-10-04 15:50
585 查看
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4465
Total Submission(s): 2888 Accepted Submission(s): 1304
Special Judge
[align=left]Problem Description[/align]
LazyChild is a lazy child who likes candy very much. Despite being very young, he has two large candy boxes, each contains n candies initially. Everyday he chooses one box and open it. He chooses the first box with probability p and
the second box with probability (1 - p). For the chosen box, if there are still candies in it, he eats one of them; otherwise, he will be sad and then open the other box.
He has been eating one candy a day for several days. But one day, when opening a box, he finds no candy left. Before opening the other box, he wants to know the expected number of candies left in the other box. Can you help him?
[align=left]Input[/align]
There are several test cases.
For each test case, there is a single line containing an integer n (1 ≤ n ≤ 2 × 105) and a real number p (0 ≤ p ≤ 1, with 6 digits after the decimal).
Input is terminated by EOF.
[align=left]Output[/align]
For each test case, output one line “Case X: Y” where X is the test case number (starting from 1) and Y is a real number indicating the desired answer.
Any answer with an absolute error less than or equal to 10-4 would be accepted.
[align=left]Sample Input[/align]
10 0.400000
100 0.500000
124 0.432650
325 0.325100
532 0.487520
2276 0.720000
[align=left]Sample Output[/align]
Case 1: 3.528175
Case 2: 10.326044
Case 3: 28.861945
Case 4: 167.965476
Case 5: 32.601816
Case 6: 1390.500000
[align=left]Source[/align]
2012 Asia Chengdu Regional Contest
【分析】:
原来这是紫书上的一道题。。
题意有两个盒子,各n个糖果,每天从其中的1个盒子中拿一个糖果。
每天从一个盒子拿的概率是p,另一个(1-p);
当某一天打开一个盒子发现空时,另一个盒子中的糖果数量的期望值是多少?
至关重要的一点,起初忽略了,上面红字!这一天相当于拿糖时空手而归。
假设A盒子,B盒子。取A的概率为p。
假设发现A空了的那一天,从B中已经取走了i个
则这种事件发生的概率为 C(n+i, i) * p^(n+1)
*(1-p)^i
但是n的取值范围可达20万,组合数特别大,p的n+1次方又特别小,直接算会损失精度。
自然对数的优化登场。
令V = C(n+i, i) * p^(n+1) *(1-p)^i
这三个数相乘,整体取对数,得ln(V)= ln(C(n+i, i))
+ (n+1)*ln(p) + i*ln(1-p)
计算过程用对数,算完之后得到ln(V)
那么该状态的概率V = e^ln(V),这时的概率将大大减少精度损失。
然后的话就是遍历i求每个状态的V*i ,求和,即为答案。别忘了A和B盒子交换一下的情况。
另外,组合数也是对数优化的,把求组合数过程的阶乘,取对数ln(n!) =ln(n) + ln(n-1) +.....
这样就能不爆longlong
【代码】:#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
using namespace std;
double lnc[404040];
double lns[401010];//ln(i)的前n项和
void init()
{
lns[1]=0;//特殊
for(int i=1;i<=200010;i++)
lns[i]=log(i)+lns[i-1];
}
double lnC(int n,int m)
{
if(m==0)return 0;
return (lns
-lns[n-m])-lns[m];
}
int main()
{
init();
int n,r=1;
double p;
while(cin>>n>>p)
{
double ans=0;
for(int i=0;i<n;i++)
{
double t=lnC(n+i,i)+(n+1)*log(p)+i*log(1-p);
ans+=exp(t)*(n-i);
t=lnC(n+i,i)+(n+1)*log(1-p)+i*log(p);//换盒子
ans+=exp(t)*(n-i);
}
printf("Case %d: %lf\n",r++,ans);
}
return 0;
}
Candy
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2888 Accepted Submission(s): 1304
Special Judge
[align=left]Problem Description[/align]
LazyChild is a lazy child who likes candy very much. Despite being very young, he has two large candy boxes, each contains n candies initially. Everyday he chooses one box and open it. He chooses the first box with probability p and
the second box with probability (1 - p). For the chosen box, if there are still candies in it, he eats one of them; otherwise, he will be sad and then open the other box.
He has been eating one candy a day for several days. But one day, when opening a box, he finds no candy left. Before opening the other box, he wants to know the expected number of candies left in the other box. Can you help him?
[align=left]Input[/align]
There are several test cases.
For each test case, there is a single line containing an integer n (1 ≤ n ≤ 2 × 105) and a real number p (0 ≤ p ≤ 1, with 6 digits after the decimal).
Input is terminated by EOF.
[align=left]Output[/align]
For each test case, output one line “Case X: Y” where X is the test case number (starting from 1) and Y is a real number indicating the desired answer.
Any answer with an absolute error less than or equal to 10-4 would be accepted.
[align=left]Sample Input[/align]
10 0.400000
100 0.500000
124 0.432650
325 0.325100
532 0.487520
2276 0.720000
[align=left]Sample Output[/align]
Case 1: 3.528175
Case 2: 10.326044
Case 3: 28.861945
Case 4: 167.965476
Case 5: 32.601816
Case 6: 1390.500000
[align=left]Source[/align]
2012 Asia Chengdu Regional Contest
【分析】:
原来这是紫书上的一道题。。
题意有两个盒子,各n个糖果,每天从其中的1个盒子中拿一个糖果。
每天从一个盒子拿的概率是p,另一个(1-p);
当某一天打开一个盒子发现空时,另一个盒子中的糖果数量的期望值是多少?
至关重要的一点,起初忽略了,上面红字!这一天相当于拿糖时空手而归。
假设A盒子,B盒子。取A的概率为p。
假设发现A空了的那一天,从B中已经取走了i个
则这种事件发生的概率为 C(n+i, i) * p^(n+1)
*(1-p)^i
但是n的取值范围可达20万,组合数特别大,p的n+1次方又特别小,直接算会损失精度。
自然对数的优化登场。
令V = C(n+i, i) * p^(n+1) *(1-p)^i
这三个数相乘,整体取对数,得ln(V)= ln(C(n+i, i))
+ (n+1)*ln(p) + i*ln(1-p)
计算过程用对数,算完之后得到ln(V)
那么该状态的概率V = e^ln(V),这时的概率将大大减少精度损失。
然后的话就是遍历i求每个状态的V*i ,求和,即为答案。别忘了A和B盒子交换一下的情况。
另外,组合数也是对数优化的,把求组合数过程的阶乘,取对数ln(n!) =ln(n) + ln(n-1) +.....
这样就能不爆longlong
【代码】:#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
using namespace std;
double lnc[404040];
double lns[401010];//ln(i)的前n项和
void init()
{
lns[1]=0;//特殊
for(int i=1;i<=200010;i++)
lns[i]=log(i)+lns[i-1];
}
double lnC(int n,int m)
{
if(m==0)return 0;
return (lns
-lns[n-m])-lns[m];
}
int main()
{
init();
int n,r=1;
double p;
while(cin>>n>>p)
{
double ans=0;
for(int i=0;i<n;i++)
{
double t=lnC(n+i,i)+(n+1)*log(p)+i*log(1-p);
ans+=exp(t)*(n-i);
t=lnC(n+i,i)+(n+1)*log(1-p)+i*log(p);//换盒子
ans+=exp(t)*(n-i);
}
printf("Case %d: %lf\n",r++,ans);
}
return 0;
}
相关文章推荐
- [概率+对数优化] hdu 4465 Candy
- Hdu 4465 Candy (概率 对数 组合数 负二项分布)
- HDU 4465 - Candy(概率与数学优化)
- HDU 4465 - Candy(概率与数学优化)
- HDU 4465 Candy (概率)
- hdu 4465 Candy - 概率 log 组合数
- HDU 4465 Candy 概率 (2012成都区域赛B题)
- hdu 4465 Candy(概率公式+极大乘极小,4级)
- hdu 4465 Candy(概率公式+极大乘极小,4级)
- hdu 4465 Candy - 概率 log 组合数
- hdu 4465 Candy(二次项概率)
- HDU 4465 Candy(概率)
- Hdu 4465 Candy (快速排列组合+概率)
- hdu 4465 Candy (概率期望)
- hdu 5245 2015 上海邀请赛(期望值 数学概率)
- hdu 4465 Candy(log压缩大数)
- hdu 4465 概率+数学处理
- hdu 4465 Candy (快速排列组合 )
- HDU 4465 candy
- hdu 4465 概率+数学处理