UVa1639糖果(紫书333)(期望)

来源:互联网 发布:mac微云如何同步 编辑:程序博客网 时间:2024/05/22 14:59
时间限制:1秒  内存限制:64M

【问题描述】

  有两个盒子各有n个糖果(n<=200000),每天随机选择一个:选第一个盒子的概率是p(0 ≤ p ≤ 1),第二个盒子的概率为1-p,然后吃掉其中的一颗。直到有一天,随机选择一个盒子打开一看,没糖了!现在请你计算另一个盒子里剩下的糖果数量的期望值。

【输入格式】

  包含多组数据。每组数据包含连个数:n和p,n是一个整数,表示每个盒子中的糖果数量,p是一个小数,表示每次打开第一个盒子的概率。

【输出格式】

  每组数据输出一个保留6位小数的实数,表示剩余糖果的期望值。

【输入样例】

10 0.400000
100 0.500000
124 0.432650
325 0.325100
532 0.487520
2276 0.720000

【输出样例】

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

【数据范围】

1 ≤ n ≤ 2×10^5

【来源】

UVa1639糖果(紫书333)

现在开始发昨天的题,昨天刷太晚就直接走了,忘了发了。

这道题要发现一个公式,我们设第1个盒子吃完发现第二个盒子里还有i个的概率为f(i)(第二个盒子吃完的反过来就好了),那我们一共就吃了2*n-i个糖,而这些糖有n个是第一盒的n-i个第二盒的,所以为:C(n,2*n-i)P^(n+1)(1-P)^(n-i).

注意一共打开了第一个盒子n+1次,比较你最后要开一次发现没有了。

这道题理解不难,直接实现也很简单,但对于精度用对数处理的方法确实让我学到了很多(开始输出过0的我不想说什么)。

学习永无止境。

代码如下:

#include<cstdlib>#include<cstdio>#include<cstring>#include<iostream>#include<cmath>using namespace std;const int maxn=400005;long double b[maxn];int n;double p,ans;int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    b[0]=0;    for(int i=1;i<=maxn-5;i++)    b[i]=b[i-1]+log(i);    int T=0;    long double x,y,z,xxx,yyy;    while(scanf("%d%lf",&n,&p)==2)    {        ans=0;        xxx=log(p),yyy=log(1-p);        for(int i=1;i<=n;i++)        {            x=b[2*n-i]-b[n]-b[n-i];            y=x+(n+1)*xxx+(n-i)*yyy;            z=x+(n+1)*yyy+(n-i)*xxx;            ans+=(double)i*(exp(y)+exp(z));        }        printf("Case %d: %.6lf\n",++T,ans);    }    return 0;}
1 0
原创粉丝点击