题意 : 初始状态 你在 1 这个点上, p 个概率向前走一步, 1-p 的概率 向前有 两步。 现在,线上分布这 n 个雷, 也就是这n 个格子不能走,问成功走出这条路的概率。
n<=10 , 雷的坐标最大是10^8
概率DP :
考虑到 雷的坐标比较大 ,不可以直接DP ,但是 n 比较小,可以分段,
对没有雷的坐标 x -> y , f[ i ] = f[ i -1] *p + f[ i-2 ]*(1 -q)
这样递推, 明显可以矩阵快速幂 递推。复杂度 lg n
注意 : 给的雷 没说排好序 , 没排序 一直TLE ,原因是矩阵快速幂是 指数出现了 负数。。
double 类型记得控eps 避免出现 -0.000000 的状态 。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-8;
#define LL long long
#define pb push_back
int a[11];
double p;
int n;
const int maxn = 110;
const int size =2;
struct Mat{
double mat[size][size];
void init(){
mat[0][0]=0;
mat[0][1]=1-p;
mat[1][0]=1;
mat[1][1]=p;
}
void Zero(){
mat[0][0]=0;
mat[0][1]=0;
mat[1][0]=0;
mat[1][1]=0;
}
void show(){
cout << mat[0][0]<<" "<<mat[0][1]<<endl;
cout << mat[1][0]<<" "<<mat[1][1]<<endl;
}
}E,g;
void init_E(){
E.mat[0][0]=1;
E.mat[0][1]=0;
E.mat[1][0]=0;
E.mat[1][1]=1;
}
Mat operator*(const Mat &a,const Mat &b){
Mat c;
for(int i=0;i<size;i++)
for(int j=0;j<size;j++){
c.mat[i][j] = 0;
for(int k=0;k<size;k++){
if(fabs(a.mat[i][k])>eps && fabs(b.mat[k][j])>eps)
c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j]);
}
}
return c;
}
Mat operator+(const Mat &a ,const Mat &b){
Mat c;
c.Zero();
for(int i=0;i<size;i++)
for(int j=0;j<size;j++){
c.mat[i][j]=(a.mat[i][j]+b.mat[i][j]);
}
return c;
}
Mat operator^(Mat a,int x){
Mat c=E;
for(;x;x>>=1){
if(x&1)
c=c*a;
a=a*a;
}
return c;
}
int len;
double st;
double get_ans(){
a[0] = 0;
st = 1;
double ans = 0;
for(int i=1;i<=n;i++){
len = a[i]- (a[i-1]+1)-1;
Mat tmp = g^len;
// cout << len <<" len "<<endl
ans = st*tmp.mat[1][1];
st = ans*(1-p);
}
return st;
}
void solve(){
bool bo = true;
a[0]=-1;
for(int i=1;i<=n;i++){
if(a[i] == a[i-1]+1 || a[i] ==1){
bo = false;
break;
}
}
double a=0;
if(bo){
a = get_ans();
}else{
a = 0;
}
printf("%.7f\n",a);
}
int main(){
init_E();
while(~scanf("%d",&n)){
scanf("%lf",&p);
g.init();
//cout << g.mat[0][1]<<" ** "<<endl;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
solve();
}
return 0;
}