3582
一个东东上下各有n个灯,灯有亮和暗两种状态,起初都是暗的,每天每盏灯亮的概率是p,各个灯独立并且一个灯亮了就不会暗掉,问上下各至少有m盏灯亮的期望是多少天。
设e(x,y)为上面亮了x盏灯,下面亮了y盏灯的期望。
则枚举本天灯亮的状态:
e(x,y)=1+sigma(e(x+i,y+j)*C(n-x,i)*C(n-y,j)*p^(i+j)*(1-p)^(n-x-i+n-y-j))
其中给你i是从0到n-x,j是从0到n-y。
注意等号右边也有e(x,y) (在i=j=0时),要移项一下。
然后可以递归之。边界条件是e(x,y)=0 if x>=m && y>=m
重复的不要重新算,并且e(x,y)=e(y.x) 用对称性可以少算一半状态。
#include<cstdio> #include<cstring> #include<iostream> #define prt(k) cout<<#k"="<<k<<endl; using namespace std; #define ll long long ll c[222][112]; int n,m; double e[222][211]; double P, p[222], p2[222]; void init() { memset(c,0,sizeof c); for(int i=0;i<66;i++) c[i][0]=c[i][i]=1; for(int i=0;i<55;i++) { for(int j=0;j<i;j++) c[i][j]=c[i-1][j-1]+c[i-1][j]; } // prt(c[6][2]) p[0]=p2[0]=1.0; for(int i=1;i<88;i++) { p[i]=p[i-1]*P; p2[i]=p2[i-1]*(1-P); } memset(e,0,sizeof e); } double get(int x,int y,int i,int j) { return c[n-x][i]*p[i]*p2[n-i-x]*c[n-y][j]*p[j]*p2[n-y-j]; } double dfs(int x,int y) { if(x>=m&&y>=m) return 0; if(e[x][y]>1e-8) return e[x][y]; e[x][y]=1.; for(int i=0;i<=n-x;i++) for(int j=0;j<=n-y;j++) { if(i==0&&j==0) continue; e[x][y]+=get(x,y,i,j)*dfs(x+i,y+j); } return e[x][y]/=(1-get(x,y,0,0)); } int main() { while(cin>>n>>m>>P&&n) { init(); printf("%.6f\n",dfs(0,0)); //cout<<dfs(0,0)<<endl; } }