poj 3744 矩阵 高斯消元

  着实被批评了一下,自己的数论确实太烂了。

  题意:一条路上,有n个炸弹,给出每个炸弹的位置,一次走一步的概率是p,走两步的概率是1-p。求安全走完的概率。

  定义dp[i] = dp[i-1]*p + dp[i-2]*(1-p)

  由于路很长,不能递推。

  n个炸弹就把路分成了n+1段路,计算走完一段路安全的概率就行,然后相乘。

             | p ,  1 |

  | dp[i-1],dp[i-2] | * | 1-p,0 |   = | dp[i],dp[i-1] |

  求安全走完一段长为L路的概率,就将矩阵乘L次即可,由于L可能很大,用二分法计算。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct mat{
    double a[2][2];
    mat()
    {for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                a[i][j]=0;
    }
};

mat e;
int n;
double p;
int num[20];
mat mul(mat a,mat b)
{
    mat ans;
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
                ans.a[i][j]+=a.a[i][k]*b.a[k][j];
    return ans;
}
double matPow(mat a,int k)
{
    mat ans=e;
    while(k)
    {
        if(k&1) ans=mul(ans,a);
        a=mul(a,a);
        k=k>>1;
    }
    return ans.a[0][0];
}
int main()
{
    e.a[0][0]=1;e.a[1][0]=0;
    e.a[0][1]=0;e.a[1][1]=1;
    while(scanf("%d%lf",&n,&p)!=EOF)
    {
        num[0]=0;
        for(int i=1;i<=n;i++)    scanf("%d",&num[i]);
        sort(num,num+n+1);
        double ans=1;
        mat res;
        res.a[0][0]=p;res.a[1][0]=1;
        res.a[0][1]=1-p;res.a[1][1]=0;
        for(int i=1;i<=n;i++)
            ans*=(1.0-matPow(res,num[i]-num[i-1]-1));
        printf("%.7lf
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yongren1zu/p/3335905.html