题意:人从1开始走,p的概率走1步,1-p的概率走2步,求踩雷的概率。
题解:走到第i位置的概率为f[i]=p*f[i-1]+(1-p)*(f[i-2]),利用矩阵快速幂可迅速求出f[i]。考虑成功通过第i个的雷的概率,应该等于没有踩中前(i-1)个雷的概率乘以没有踩中i的概率,而如果没有踩到i-1这颗雷,人必定是从mine[i-1]+1过来的,于是又变成和原来一样的解情况。考虑从1出发顺利通过位于x处的雷的概率,就应该等于一减去踩到x这个位置的概率,而踩到x的概率应该等于f[x],于是,得解。
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 double mat[200][2][2]; 6 void update(int ID) 7 { 8 memset(mat[ID],0,sizeof(mat[ID])); 9 for(int i=0;i<2;i++) 10 for(int j=0;j<2;j++) 11 for(int k=0;k<2;k++) 12 mat[ID][i][j]+=mat[ID-1][i][k]*mat[ID-1][k][j]; 13 } 14 int mine[20]; 15 int main() 16 { 17 int n; 18 double p; 19 while(scanf("%d%lf",&n,&p)!=EOF) 20 { 21 for(int i=0;i<n;i++) 22 scanf("%d",mine+i); 23 sort(mine,mine+n); 24 mat[0][0][0]=p; 25 mat[0][0][1]=1.0; 26 mat[0][1][0]=1.0-p; 27 mat[0][1][1]=0; 28 for(int i=1;i<200;i++) 29 update(i); 30 double ans=1; 31 int lx=1,len,k; 32 for(int i=0;i<n;i++) 33 { 34 len=mine[i]-lx; 35 double x[2],y[2]; 36 x[0]=1.0;x[1]=0.0; 37 k=0; 38 while(len>0) 39 { 40 if(len&1) 41 { 42 y[0]=x[0]*mat[k][0][0]+x[1]*mat[k][1][0]; 43 y[1]=x[0]*mat[k][0][1]+x[1]*mat[k][1][1]; 44 x[0]=y[0];x[1]=y[1]; 45 } 46 len>>=1; 47 k++; 48 } 49 ans*=(1-x[0]); 50 lx=mine[i]+1; 51 } 52 printf("%.7lf\n",ans); 53 } 54 return 0; 55 }