hdu 4465 Candy (数值计算 概率)

来源:互联网 发布:3DM看门狗卡顿优化补丁 编辑:程序博客网 时间:2024/05/29 14:03

Candy

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 617    Accepted Submission(s): 274
Special Judge

Problem Description
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?
 

Input
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.
 

Output
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.
 

Sample Input
10 0.400000100 0.500000124 0.432650325 0.325100532 0.4875202276 0.720000
 

Sample Output
Case 1: 3.528175Case 2: 10.326044Case 3: 28.861945Case 4: 167.965476Case 5: 32.601816Case 6: 1390.500000
 

Source
2012 Asia Chengdu Regional Contest
 

ps:这题是2012年成都区域赛题   数值计算题   计算概率  因为没搞过数值计算  所以打联系赛做这题时直接放弃了   还是有点可惜的  这题应该是数值计算中的偏水的题吧 
数学呀  好重要  以后不能把这块放着不动了  
 
思路:首先是推公式   推公式时要注意最后一次他发现一个盒子为空的时的概率也要计算上去  因为必须要你再选择一次这个盒子  你才会发现这个盒子是空的  
所以推出来的公式为
期望=(2*n-x)*C(x n)*(p*p^n*q^(x-n)+q*q^n*p^(x-n))      
x~一共吃了多少糖 x从n取到2*n              q~1-p
然后就是直接计算的话   计算C(x n)是要上溢的 计算p^n是要下溢的 必须要取log来算   这是一个技巧  
顺便说一下  计算log时能打表的一定打表  因为log函数本身也是很花时间滴

代码:
#include <cstdio>#include <cmath>#define maxn 400005using namespace std;int n,m;double p,q,ans;double lg[maxn],sum[maxn];int main(){    int i,j,t=0;    double tmp,lgp,lgq;    sum[0]=0;    for(i=1;i<maxn;i++)          // 打表呀打表    {        lg[i]=log(i*1.0);        sum[i]=sum[i-1]+lg[i];    }    while(~scanf("%d%lf",&n,&p))    {        ans=0;        t++;        q=1-p;        lgp=log(p*1.0);    // 最好先把log算出来  不然到下面的循环中算很费时间        lgq=log(q*1.0);        for(i=n;i<2*n;i++)        {            tmp=(2*n-i)*exp(sum[i]-sum[n]-sum[i-n]+(n+1)*lgp+(i-n)*lgq);  // sum[i]-sum[n]-sum[i-n] 为计算log(C(i,n)) 然后exp()就还原了            ans+=tmp;            tmp=(2*n-i)*exp(sum[i]-sum[n]-sum[i-n]+(n+1)*lgq+(i-n)*lgp);            ans+=tmp;        }        printf("Case %d: %.6lf\n",t,ans);    }    return 0;}