题意: 从1开始每次有p的概率往前跳一步,1-p的概率跳两步。给定n个点以及它们的坐标,若跳到这些点上则算失败,求安全经过这些点的概率。
分析:容易推出 dp[i] = dp[i-1]*p + dp[i-2]*(1-p) ; 把n个点的坐标从小到大排序,每两个点之间为一段,若要来到下一段必须从上一段跳到下一段的第一个点。又因为 n<=10 ,设所求最终概率为 ans ,
则 ans =( 1 - dp[ n1 - 1] ) * ( 1 - dp[ n2 - n1 - 1 ] ) * ... * ( 1 - dp[ nn - nn-1 -1 ] ) ;
但因为点的坐标 1 <= xi <= 1e8 ; 直接顺推会超时 ,所以需要用到矩阵快速幂加速优化。。
=
*
=
*
^ Dis
Dis为每相邻两个点之间的距离
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int n;
double p;
int x[11];
struct Matrix
{
double mat[2][2];
};
Matrix operator * (Matrix a,Matrix b)
{
Matrix c;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
{
c.mat[i][j]=0;
for(int k=0;k<2;k++)
c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
}
return c;
}
Matrix operator ^ (Matrix a,ll k)
{
Matrix c;
memset(c.mat,0,sizeof(c.mat));
c.mat[0][0]=c.mat[1][1]=1; //单位矩阵为基底
while(k)
{
if(k&1) c=c*a;
a=a*a;
k>>=1;
}
return c;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n>>p)
{
for(int i=1;i<=n;i++) cin>>x[i];
sort(x+1,x+n+1);
Matrix c;
c.mat[0][0]=p , c.mat[0][1]=1 ,
c.mat[1][0]=1-p, c.mat[1][1]=0 ;
double ans=1.0;
Matrix k=c^(x[1]-1);
ans*=(1-k.mat[0][0]);
for(int i=2;i<=n;i++)
{
k=c^(x[i]-x[i-1]-1);
ans*=(1-k.mat[0][0]);
}
printf("%.7f\n",ans);
}
return 0;
}