题意:人从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 }