Scout YYF I 概率dp + 矩阵快速幂

来源:互联网 发布:离散数学教材推荐 知乎 编辑:程序博客网 时间:2024/06/06 01:41
/*    题目描述:在一条道路上,每个位置有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|1using 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;}

0 0