/*
题目描述:在一条道路上,每个位置有1个编号,编号分别是1 , 2 , ......现在有n(1 <= n <= 10)颗地雷,第i个分布位置的
处的编号为x[i],其中1 <= x[i] <= 100000000 现有一个人从位置1开始,问他在不踩到地雷的情况下穿过这条路
的概率
方法:设dp[i]表示刚走过第i个地雷而且活着的概率,而刚走过第i个地雷,就说明这个人现在的位置是x[i] + 1,因为经
过地雷只有一种情况,就是从x[i] - 1到x[i] + 1。
设step[i]表示从下标为p处走到p + i处的概率,可知step[i] = p * step[i - 1] + (1 - p) * step[i - 2],且step[0] = 1,
step[1] = p,因为需要计算的i可能等于1e8,所以step的计算需要矩阵快速幂,矩阵的形式如下:
| p 1-p|^(n - 1) | p 0| = | step[n] 0|
| 1 0 | | 1 0| | step[n - 1] 0|
那么,dp[i] = dp[i - 1] *(step[dis] - p * step[dis - 1]) dis是从x[i - 1] + 1到x[i] + 1需要走的步数
具体见代码
*/
#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-6;
const int maxn = 50 + 5;
const int NUM = 2;
double dp[maxn];
int x[maxn];
struct Matrix
{
double a[NUM][NUM] ;
void init(){
mem(a , 0);
for(int i = 0 ; i<NUM ; i++){
a[i][i] = 1;
}
}
};
Matrix mul(Matrix a , Matrix b)
{
Matrix ans;
for(int i = 0 ; i< NUM ; i++){
for(int j = 0 ; j<NUM ; j++){
ans.a[i][j] = 0;
for(int k = 0 ; k<NUM ; k++){
ans.a[i][j] += a.a[i][k] * b.a[k][j];
}
}
}
return ans;
}
Matrix qpow(Matrix a , int n)
{
Matrix ans;
ans.init();
while(n){
if(n & 1) ans = mul(ans , a);
n >>= 1;
a = mul(a , a);
}
return ans;
}
int main()
{
int n;
double p;
while(scanf("%d %lf", &n , &p) != EOF){
for(int i = 1 ; i <= n ; i++){
scanf("%d", &x[i]);
}
Matrix multi , origin;
multi.a[0][0] = p; multi.a[0][1] = 1 - p;
multi.a[1][0] = 1; multi.a[1][1] = 0;
mem(origin.a , 0);
origin.a[0][0] = p;
origin.a[1][0] = 1;
sort(x + 1 , x + 1 + n);
int flag = 1;
for(int i = 2 ; i<= n ; i++){
if(x[i] == x[i - 1]){
flag = 0;
break;
}
}
if(x[1] == 1) flag =0;
if(!flag){
puts("0.0000000");
continue;
}
int pos = 1;
dp[0] = 1;
for(int i = 1 ; i<= n ; i++){
int dis = x[i] + 1 - pos;
Matrix ret = mul(qpow(multi , dis - 1) , origin);
double pro1 = ret.a[0][0] , pro2 = ret.a[1][0];
dp[i] = dp[i - 1] * (pro1 - p * pro2);
pos = x[i] + 1;
}
printf("%.7lf\n",dp[n]);
}
return 0;
}
Scout YYF I 概率dp + 矩阵快速幂
最新推荐文章于 2021-10-18 16:29:31 发布