分析:
显然是一道概率DP
令
f
i
f_i
fi表示安全到达第
i
i
i格的概率,在不考虑地雷的情况下,显然有:
f
1
=
1
,
f
2
=
p
,
f
i
=
p
f
i
−
1
+
(
1
−
p
)
f
i
−
2
(
i
>
=
3
)
f_1 = 1,f_2 = p,f_i = pf_{i - 1} + (1 - p)f_{i - 2}\,(i >= 3)
f1=1,f2=p,fi=pfi−1+(1−p)fi−2(i>=3)
那加上地雷呢?
注意到
n
<
=
10
n <= 10
n<=10,分开处理不就好了,可以分开计算每两个相邻地雷间的区域,遇到地雷就跳过,即:
f
地
雷
后
=
(
1
−
p
)
f
地
雷
前
f_{地雷后} = (1 - p)f_{地雷前}
f地雷后=(1−p)f地雷前
但
a
i
<
=
1
0
8
a_i <= 10^8
ai<=108,会超时?
注意到这是一个二阶线性递推数列,用特征方程,解得:
f
n
=
f
1
(
(
p
−
1
)
n
−
1
)
p
−
2
\sout{f_n = \frac{f_1((p - 1) ^ n - 1)}{p - 2}}
fn=p−2f1((p−1)n−1),快速幂求就好了~
可以用矩阵快速幂优化,令
F
n
=
[
f
n
f
n
−
1
]
,
G
=
[
p
1
−
p
1
0
]
F_n = \left[\begin{matrix}f_n\\f_{n - 1}\end{matrix}\right],G =\left[\begin{matrix}p &1 - p \\ 1 & 0 \end{matrix}\right]
Fn=[fnfn−1],G=[p11−p0]
则有
F
n
=
F
n
−
1
G
F_n = F_{n - 1}G
Fn=Fn−1G
即
F
n
=
F
1
G
n
−
1
F_n = F_1G ^ {n - 1}
Fn=F1Gn−1
最后跑快速幂即可
注意特判两个地雷相邻的情况
Code:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 15;
int n,a[maxn];
double p,f;
struct matrix{
double num[5][5];
}F;
int read(){
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
return x;
}
matrix mul(matrix x,matrix y){
matrix d;
for(int i = 1; i <= 2; i ++){
for(int j = 1; j <= 2; j ++){
d.num[i][j] = 0;
for(int k = 1; k <= 2; k ++) d.num[i][j] += x.num[i][k] * y.num[k][j];
}
}
return d;
}
matrix qpow(matrix x,int k){
matrix t = x,d;
d.num[1][1] = d.num[2][2] = 1,d.num[1][2] = d.num[2][1] = 0;
while(k){
if(k & 1) d = mul(d,t);
k >>= 1,t = mul(t,t);
}
return d;
}
int main(){
while(~scanf("%d%lf",&n,&p)){
for(int i = 1; i <= n; i ++) a[i] = read();
sort(a + 1,a + 1 + n);
f = 1,F.num[1][1] = p,F.num[1][2] = 1 - p,F.num[2][1] = 1,F.num[2][2] = 0;
for(int i = 1; i <= n; i ++){
if(a[i] - a[i - 1] == 1){//如果相邻,肯定走不出去
f = 0;
break;
}
if(i != 1) f *= (1 - p);// 如果不是第一段,当前段第一格的概率为从上一段的最后一格跳两格的概率
f *= qpow(F,a[i] - a[i - 1] - 2).num[1][1];//f变为当前段最后一格的概率
}
printf("%.7f\n",f * (1 - p));//最后一段右边还有一个地雷,做完这题才知道输出double要用%f,这题用%lf会WA!调了好久qwq
}
return 0;
}