解题思路:
dp[i] = p * dp[i-1] + (1 - p) * dp[i-2]; 由于N比较大,dp[i]需要用矩阵快速幂求解。
安全通过整段路的概率等于安全通过每一个两个炸弹区间的概率乘积。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
const int maxn = 1000000 + 10;
typedef vector<double> vec;
typedef vector<vec> mat;
mat mul(mat &A, mat &B)
{
mat C(A.size(), vec(B[0].size()));
for(int i=0;i<A.size();i++)
{
for(int k=0;k<B.size();k++)
{
for(int j=0;j<B[0].size();j++)
{
C[i][j] = (C[i][j] + A[i][k] * B[k][j]);
}
}
}
return C;
}
mat POW(mat A, int n)
{
mat B(A.size(), vec(A.size()));
for(int i=0;i<A.size();i++)
B[i][i] = 1;
while(n)
{
if(n & 1) B = mul(B, A);
A = mul(A, A);
n >>= 1;
}
return B;
}
int P[maxn];
int main()
{
int N; double p;
while(cin>>N>>p)
{
for(int i=0;i<N;i++)
cin>>P[i];
sort(P , P + N);
mat A(2,vec(2));
A[0][0] = p, A[0][1] = 1;
A[1][0] = 1-p, A[1][1] = 0;
mat tmp(2,vec(2));
tmp = POW(A, P[0] - 1);
double ans = 1 - tmp[0][0];
for(int i=1;i<N;i++)
{
if(P[i] == P[i-1]) continue;
tmp = POW(A, P[i]-P[i-1]-1);
ans *= (1 - tmp[0][0]);
}
printf("%.7f\n", ans);
}
return 0;
}