矩陣快速冪應用於概率DP POJ 3744
阿新 • • 發佈:2019-01-29
第一次構造了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; }