1. 程式人生 > >矩陣快速冪應用於概率DP POJ 3744

矩陣快速冪應用於概率DP POJ 3744

第一次構造了2*2的矩陣,不成功:

matrix[2][2]={p,1.0,1.0-p,0}

#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define CLEAR(a) memset((a),0,sizeof((a)))

using namespace std;

typedef long long LL;
const double pi = acos(-1.0);
const int maxn=1e4;
const int inf=99999999;
const float eps=1e-3;
vector<int> vec;
double f[maxn];

struct Matrix
{
    double x00,x01,x10,x11;
    Matrix(){};
    Matrix(double x00,double x01,double x10,double x11)
    {
        this->x00=x00;
        this->x01=x01;
        this->x10=x10;
        this->x11=x11;
    }
    Matrix(double p)
    {
        this->x00=p;
        this->x01=1.0;
        this->x10=1.0-p;
        this->x11=0;
    }

    double GetResult()
    {
        return this->x11;
    }
};

    Matrix operator*(const Matrix& a,const Matrix &b)
    {
        return Matrix(a.x00*b.x00+a.x01*b.x10,a.x00*b.x01+a.x01*b.x11,a.x10*b.x00+a.x11*b.x10,a.x10*b.x01+a.x11*b.x11);
    }

    Matrix operator^(const Matrix& a,int n)
    {
        if (n==1) return a;
        else if (n&1) return (a^((n-1)>>1))*(a^((n+1)>>1));
        else return (a^(n>>1))*(a^(n>>1));
    }

int main()
{
    int n;
    double p;
    while (~scanf("%d%lf",&n,&p))
    {
        vec.clear();
        CLEAR(f);
        for(int i=0;i<n;i++)
        {
            int x;
            scanf("%d",&x);
            vec.push_back(x);
        }
        sort(vec.begin(),vec.end());
        for(int i=0;i<n;i++)
        {
            if (i>0)
            {
                Matrix m(f[i-1]);
                f[i]=(m^(vec[i]-vec[i-1])).GetResult();
            }
            else
            {
                Matrix m(1);
                f[i]=(m^(vec[i]-1)).GetResult();
            }
        }
        printf("%.7lf",f[*vec.end()]);
    }
    return 0;
}


第二次,用到了單位矩陣:

{1,0,0,1}

#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define CLEAR(a) memset((a),0,sizeof((a)))
using namespace std;

const double eps = 1e-8;
const double pi = acos(-1.0);
typedef long long LL;
const int maxn = 15;
int m = 2;
int mine[maxn];
class Matrix
{
    public:
        double num[3][3];
        Matrix()
        {
            CLEAR(num);
        }
        Matrix(double p)
        {
            CLEAR(num);
            num[0][0] = p;
            num[0][1] = 1 - p;
            num[1][0] = 1;
            num[1][1] = 0;
        }
        static Matrix One()
        {
            Matrix res;
            res.num[0][0] = 1;
            res.num[1][1] = 1;
            return res;
        }
        Matrix operator*(const Matrix& b)
        {
            Matrix a = *this, ans;
            for (int i = 0; i < m; i++)
                for (int j = 0; j < m; j++)
                    for (int k = 0; k < m; k++)
                    {
                        ans.num[j][k] += a.num[j][i] * b.num[i][k];
                    }
            return ans;
        }
        Matrix operator*= (const Matrix& b)
        {
            *this = *this * b;
            return *this;
        }
};
Matrix pow(Matrix matrix, int n)
{
    Matrix res = Matrix::One();
    while (n)
    {
        if (n & 1)
        {
            res *= matrix;
        }
        matrix *= matrix;
        n >>= 1;
    }
    return res;
}
double getRes(int t, double p)
{
    if (t <= 1)
    {
        return 0;
    }
    if (t == 2)
    {
        return 1;
    }
    if (t == 3)
    {
        return p;
    }
    t -= 3;
    Matrix matrix(p);
    matrix = pow(matrix, t);
    return matrix.num[0][0] * p + matrix.num[0][1];
}
int main()
{
    int n;
    double p;
    while (~scanf("%d%lf", &n, &p))
    {
        mine[0] = 0;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", mine + i);
        }
        sort(mine + 1, mine + n + 1);
        double ans = 1;
        for (int i = 1; i <= n; i++)
        {
            ans *= getRes(mine[i] - mine[i - 1], p);
            ans *= 1.0 - p;
        }
        printf("%.7lf\n", ans);
    }
    return 0;
}