poj 3744(概率dp、矩陣快速冪)
/*
poj 3744
題目大概是
小明要走一段路
有p的概率走一步
(1-p)的概率走兩步
然後上面有雷
問安全通過的概率
題目通過雷把路程分爲多段
把每段安全通過的概率相乘
就是整段安全通過的概率
設dp[i]是小明安全到i的概率
到i的方式有兩種
一種是從(i-1)走一步
第二種是從(i-2)走兩步
所以安全到dp[i]的概率就是
dp[i]=p*dp[i-1]+(1-p)dp[i-2]
因爲數據問題
用矩陣來優化代碼
最後把所求的每一段相乘即可
*/
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define mod 1000000007
#define MAX 100005
#define ll long long
#define PI acos(-1)
using namespace std;
struct matrix
{
double m[2][2];
}mat;
int res[15];
matrix matrixmul(matrix a,matrix b)
{
matrix c;
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
{
c.m[i][j]=0;
for(int k=0; k<2; k++)
c.m[i][j]+=(a.m[i][k]*b.m[k][j]);
}
return c;
}
matrix quickpow(matrix m,ll n)
{
matrix b;
memset(b.m,0,sizeof(b.m));
b.m[0][0]=b.m[1][1]=1;
while(n>=1)
{
if(n&1)
b=matrixmul(b,m);
n=n>>1;
m=matrixmul(m,m);
}
return b;
}
int main()
{
double ans[15];
int n;
double p;
while(cin>>n>>p)
{
mat.m[0][0]=p;
mat.m[0][1]=1-p;
mat.m[1][0]=1;
mat.m[1][1]=0;
memset(res,0,sizeof(res));
for(int i=1;i<=n;i++)
cin>>res[i];
sort(res+1,res+1+n);
matrix tmp=quickpow(mat,res[1]-1);
ans[1]=1-tmp.m[0][0];//求安全通過第一段的概率
for(int i=2;i<=n;i++)//求從第(i-1)個雷安全到第i個雷的概率
{
tmp=quickpow(mat,res[i]-res[i-1]-1);
ans[i]=1-tmp.m[0][0];
}
double rel=1;
for(int i=1;i<=n;i++)//全部相乘得結果
{
rel*=ans[i];
}
printf("%.7lf\n",rel);
}
return 0;
}
poj 3744
題目大概是
小明要走一段路
有p的概率走一步
(1-p)的概率走兩步
然後上面有雷
問安全通過的概率
題目通過雷把路程分爲多段
把每段安全通過的概率相乘
就是整段安全通過的概率
設dp[i]是小明安全到i的概率
到i的方式有兩種
一種是從(i-1)走一步
第二種是從(i-2)走兩步
所以安全到dp[i]的概率就是
dp[i]=p*dp[i-1]+(1-p)dp[i-2]
因爲數據問題
用矩陣來優化代碼
最後把所求的每一段相乘即可
*/
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define mod 1000000007
#define MAX 100005
#define ll long long
#define PI acos(-1)
using namespace std;
struct matrix
{
double m[2][2];
}mat;
int res[15];
matrix matrixmul(matrix a,matrix b)
{
matrix c;
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
{
c.m[i][j]=0;
for(int k=0; k<2; k++)
c.m[i][j]+=(a.m[i][k]*b.m[k][j]);
}
return c;
}
matrix quickpow(matrix m,ll n)
{
matrix b;
memset(b.m,0,sizeof(b.m));
b.m[0][0]=b.m[1][1]=1;
while(n>=1)
{
if(n&1)
b=matrixmul(b,m);
n=n>>1;
m=matrixmul(m,m);
}
return b;
}
int main()
{
double ans[15];
int n;
double p;
while(cin>>n>>p)
{
mat.m[0][0]=p;
mat.m[0][1]=1-p;
mat.m[1][0]=1;
mat.m[1][1]=0;
memset(res,0,sizeof(res));
for(int i=1;i<=n;i++)
cin>>res[i];
sort(res+1,res+1+n);
matrix tmp=quickpow(mat,res[1]-1);
ans[1]=1-tmp.m[0][0];//求安全通過第一段的概率
for(int i=2;i<=n;i++)//求從第(i-1)個雷安全到第i個雷的概率
{
tmp=quickpow(mat,res[i]-res[i-1]-1);
ans[i]=1-tmp.m[0][0];
}
double rel=1;
for(int i=1;i<=n;i++)//全部相乘得結果
{
rel*=ans[i];
}
printf("%.7lf\n",rel);
}
return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.