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; }