Description
YYF是一个英勇的侦查员。现在他正在执行打入到敌方内部的危险任务。在解决了一系列的险情后,YYF到达了敌方著名的"地雷路"起始点。这条路非常长,上面被精心排布了不少地雷。一开始,YYF站在1的位置。对于后面的路程,YYF有p的概率向前走一步,或者有1−p的概率向前跳两步。现在问题来了。非常喜欢坑队友的情报部得到了每个地雷的位置,但他们不准备告诉YYF,反而请你计算YYF能安全走过整条“地雷路”的概率。
Input
输入有多组数据,并由EOF结束.
每组数据由两行组成。
第一行是地雷的数量N and p 被一个空格分割。
第二行有n个数字,指代每个地雷的位置。
Output
对于每组数据,输出一行,为安全走过的概率,并保留7位小数。
Sample Input
1 0.5
2
2 0.5
2 4
Sample Output
0.5000000
0.2500000
HINT
1≤N≤10
0.25≤p≤0.75
地雷的位置∈[1,100000000]
DP:
d
p
[
i
]
dp[i]
dp[i]表示走过点i时踩雷不幸身亡的概率
d
p
[
i
]
=
d
p
[
i
−
1
]
∗
p
+
d
p
[
i
−
2
]
∗
(
1
−
p
)
dp[i]=dp[i-1]*p+dp[i-2]*(1-p)
dp[i]=dp[i−1]∗p+dp[i−2]∗(1−p)
但是数据中地雷的位置的范围过大,肯定不能直接转移。
想到矩阵快速幂
∣
p
1
−
p
1
0
∣
\begin{vmatrix} p & 1-p \\ 1 & 0 \end{vmatrix}
∣∣∣∣p11−p0∣∣∣∣
这个就是初始矩阵,用矩阵快速幂优化DP
#include<bits/stdc++.h>
using namespace std
;
int n
,a
[11];
double ans
,p
;
struct data
{
double a
[2][2];
}t
,none
;
data
operator *(data a
,data b
)
{
data c
=none
;
for(int i
=0;i
<=1;i
++)
{
for(int j
=0;j
<=1;j
++)
{
for(int k
=0;k
<=1;k
++)
{
c
.a
[i
][k
]+=a
.a
[i
][j
]*b
.a
[j
][k
];
}
}
}
return c
;
}
data
poww(data a
,int x
)
{
data sum
=none
,num
=a
;
sum
.a
[1][1]=sum
.a
[0][0]=1.0;
while(x
)
{
if(x
&1)
{
sum
=(sum
*num
);
}
x
/=2;
num
=(num
*num
);
}
return sum
;
}
int main()
{
while(scanf("%d%lf",&n
,&p
)!=EOF)
{
ans
=1.0;
for(int i
=1;i
<=n
;i
++)
{
scanf("%d",&a
[i
]);
}
sort(a
+1,a
+n
+1);
t
.a
[0][0]=p
;
t
.a
[0][1]=1-p
;
t
.a
[1][0]=1.0;
t
.a
[1][1]=0.0;
for(int i
=1;i
<=n
;i
++)
{
data tmp
;
if(i
==1)
{
tmp
=poww(t
,a
[i
]-1);
}else{
tmp
=poww(t
,a
[i
]-a
[i
-1]-1);
}
ans
=(ans
*(1-tmp
.a
[0][0]));
}
printf("%.7lf\n",ans
);
}
return 0;
}