ZOJ 10th Anniversary Contest - B Back to the Past
#include<stdio.h> #include<string.h> inline void swap(int & a,int & b) { int k=a; a=b; b=k; } const int N=50; long long binomial[N+1][N+1]; void init() { int i,j; for (i=0;i<=N;i++) { binomial[i][0]=binomial[i][i]=1; for (j=1;j<i;j++) { binomial[i][j]=binomial[i-1][j-1]+binomial[i-1][j]; } } } double p1[N+1]={1},p0[N+1]={1}; inline double oneDay(int n,int m) { return binomial[n][m]*p1[m]*p0[n-m]; } double f[N+1][N+1][N+1][N+1]; bool calc[N+1][N+1][N+1][N+1]; double getF(int n1,int m1,int n2,int m2) { if (m1<0) m1=0; if (m2<0) m2=0; if (m1==0&&m2==0) return 0; if (n1<n2) { swap(n1,n2); swap(m1,m2); } double & ff=f[n1][m1][n2][m2]; if (!calc[n1][m1][n2][m2]) { ff=oneDay(n1,0)*oneDay(n2,0); int k1,k2; for (k1=0;k1<=n1;k1++) for (k2=0;k2<=n2;k2++) { if (k1==0&&k2==0) continue; double p=oneDay(n1,k1)*oneDay(n2,k2); ff+=p*(1+getF(n1-k1,m1-k1,n2-k2,m2-k2)); } ff/=(1-oneDay(n1,0)*oneDay(n2,0)); calc[n1][m1][n2][m2]=true; } return ff; } int main() { init(); int n,m; double p; while (1) { scanf("%d%d%lf",&n,&m,&p); if (n==0&&m==0&&p==0) { break; } int i; for (i=1;i<=n;i++) { p1[i]=p1[i-1]*p; p0[i]=p0[i-1]*(1-p); } memset(calc,false,sizeof(calc)); printf("%.6f\n",(double)getF(n,m,n,m)); } return 0; }