pku 3744 Scout YYF I
把对应的坐标,换成要走的步数F(n)表示从原点走n步的概率。
易根据题意得到F(n)=p*F(n-1)+q*F(n-2) 其中F(0)=0,F(1)=1,q=1-p
用矩阵二分加速:
[F(n) F(n-1)] = [1 0] [p q]
[0 1] * [1 0]^(n-1)
对于第一个要走n步的雷,特工要存活就必须跨过这个雷,也就是走n-1步。在跨2步。这个概率就是F(n-1)*q.再以这个点为起点,计算
跨过下个雷的概率。相乘即可。
注意2个必死的情况。当有连续2颗雷,必死。当起点有雷,必死。
注意G++输出%lf和%f的问题。
#include <stdio.h>
#include <algorithm>
using namespace std;
#define MAXR 2
#define MAXC 2
struct Matrix
{
Matrix();
Matrix(double arr[MAXR][MAXC]);
int row,col;
double a[MAXR][MAXC];
/* void display()
{
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
printf("%.7lf ",a[i][j]);
}
printf("\n");
}
}*/
};
Matrix::Matrix()
{
row=MAXR;
col=MAXC;
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
if(i==j) a[i][j]=1;
else a[i][j]=0;
}
Matrix::Matrix(double arr[MAXR][MAXC])
{
row=MAXR;
col=MAXC;
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
a[i][j]=arr[i][j];
}
}
}
Matrix operator*(const Matrix &M1,const Matrix &M2)
{
Matrix M3;
for(int i=0;i<M1.row;i++)
{
for(int j=0;j<M2.col;j++)
{
M3.a[i][j]=0;
for(int k=0;k<M1.col;k++)
{
M3.a[i][j]=M3.a[i][j]+M1.a[i][k]*M2.a[k][j];
}
}
}
return M3;
}
Matrix solve(Matrix a,long n)
{
n--;
Matrix s;
while(n>0)
{
if(n&1) s=s*a;
a=a*a;
n>>=1;
}
return s;
}
int main()
{
int N;
double p,ans;
while(scanf("%d %lf",&N,&p)!=EOF)
{
int i;
bool safe=true;
int mines[11]={0};
for(i=1;i<=N;i++) scanf("%d",&mines[i]);
sort(mines+1,mines+N+1);
if(mines[1]==1)
{
printf("0.0000000\n");
// printf("%.7lf\n",0.0);
continue;
}
for(i=2;i<=N;i++)
if(mines[i]-mines[i-1]==1)
{
printf("0.0000000\n");
// printf("%.7lf\n",0.0);
safe=false;
break;
}
if(!safe) continue;
double arr[MAXR][MAXC]={{p,1.0},{1.0-p,0.0}};
Matrix a(arr),s;
ans=1.0;
for(i=1;i<=N;i++)
{
s=solve(a,mines[i]-mines[i-1]-1);
ans*=s.a[0][0]*(1.0-p);
}
printf("%.7lf\n",ans);
}
return 0;
}
浙公网安备 33010602011771号