hdu 4465

2012 ICPC/ACM 成都现场赛B题

现场赛时,理解错题意了。。一直都推不出期望的通项公式,后来赛后题解老师说很简单的期望公式,我就有点纳闷了,是我把数学忘得太厉害了吧。。后来回来再看题意,完全就理解错了。。应该是第n+1次取到同一个盒子的糖时的概率,不是第n次的时候,所以可以直接去组合数就可以了。。期望公式就很容易求了。。

题意:输入m,p;从两个盒子里各有n颗糖,每天取一颗,发现其中
一个盒子空,求另外一个盒子糖果数的期望。p,1-p为取糖概率;
for (i=0;i<n;++i)
     ans+=(n-i)*c(n,n+i)*(p^(n+1)*p^i+(1-p)^(n+1)*p^i);
n<=200200;太大,会爆double,边乘边除TLE了;后面搜了下解题报告,看到他们用取对数的方法,解决了爆double和时间的问题。。唉,太弱啊。。继续加油。。

TLE代码:

#include<stdio.h>
#include<string.h>
double quickpow(double m,int n)
{
    double b=1;
    while (n>0)
    {
        if (n&1)
            b=b*m;
        n=n>>1;
        m=m*m;
    }
    return b;
}
int main ()
{
    int n;
    double p,ans,ret;
    int i,j,k=0;
    while (scanf("%d%lf",&n,&p)!=EOF)
    {
        ans=0;
        for (i=0;i<n;++i)
        {
            ret=n-i;
            for (j=1;j<=i;++j)
                ret*=(p*(1-p)*(n+j)/j);
            ans+=(ret*quickpow(p,n-i+1));
            ans+=(ret*quickpow(1-p,n-i+1));
        }
        printf("Case %d: %.6lf\n",++k,ans);
    }
    return 0;
}

AC代码:

/*
题意如上所述;
for (i=0;i<n;++i)
    ans+=(n-i)*c(n,n+i)*(p^(n+1)*p^i+(1-p)*(n+1)*p^i);
先取对数预处理计算n!,之后调用函数求logc;最后还原。
Time:828ms 效率还是不太行。。
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 400200
double f[N];
double logc(int n,int m)
{
    return f[m]-f[n]-f[m-n];
}
int main ()
{
    int n;
    int i,j,k=0;
    double p,ans,ret;
    f[0]=0;
    for (i=1;i<N;++i) f[i]=f[i-1]+log(1.0*i);
    while (scanf("%d%lf",&n,&p)!=EOF)
    {
        ans=0;
        double p1=log(p),p2=log(1-p);
        double q1=(n+1)*p1,q2=(n+1)*p2;
        for (i=0;i<n;++i)
        {
            ans+=((n-i)*exp(logc(n,n+i)+q1+i*p2));
            ans+=((n-i)*exp(logc(n,n+i)+q2+i*p1));
        }
        printf("Case %d: %.6lf\n",++k,ans);
    }
    return 0;
}

 

 

 

posted @ 2012-11-23 00:39  _hikaru__  阅读(545)  评论(0编辑  收藏  举报