poj 3744 题解

题目

题意: $ yyf $ 一开始在 $ 1 $ 号节点他要通过一条有 $ n $ 个地雷的道路,每次前进他有 $ p $ 的概率前进一步,有 $ 1-p $ 的概率前进两步,问他不领盒饭的概率。

对于这道题我们可以考虑 $ dp $ ,我们可以设计状态 $ f[i] $ 表示安全通过 $ i $的概率,那么我们可以得到状态转移方程

$ f[i]=p* f[i-1]+(1-p)* f[i-2] $

$ f[x_i]=0 $

然后我们可以看到 $ x \in [1, 100000000] $如果我们直接 $ dp $ 很明显会超时那么怎么办呢?我们可以去考虑进行分段 $ dp $ 。我们可以观察发现在你到一个地雷前,这其中的概率只与这个地雷有关就可以把区间进行缩小然后 $ dp $

$ a[1],a[2],a[3]......a[x[1]] $

$ a[x[1]+1],a[x[1]+2],a[x[1]+3]......a[x[2]] $

$ .......... $

$ a[x[n-1]+1],a[x[n-1]+2],a[x[n-1]+3]......a[x[n]] $

然后我们看到这个状态转移方程

$ f[i]=p* f[i-1]+(1-p)* f[i-2] $

是不是很像

$ f[i]=f[i-1]+ f[i-2] $

就可以看作斐波那契数列加了个参数可以使用矩阵加速(对于这个网上有很多题解,这里就不讲这个讲下别的)

我们可以利用这个式子的特征方程进行求解(关于这一类方程

首先我们可以写出它的特征方程 $ x^2=px+* (1-p) $

移项后得 $ x^2-px+p-1=0 $

利用求根公式得到两个不同的可行解 $ x_1=p-1      x_2= 1 $

就可以写出通项公式 $ f(n)=c_1x_1^n+c_2x_2^n $

即 $ f(n)=c_1* 1^n +c_2 * (p-1)^n $

然后我们可以将 $ f(1)=1,f(2)=p $ 带入可以知道 $ c_1=\frac{1}{2-p}     c_2=\frac{1}{p-2} $

最后的通项公式就是 $ f(n)=\frac{1-(p-1)^n}{2-p} $

最后用快速幂求出 $ 1-(p-1)^n $ 即可

代码

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,x[30];
double p,ans;
double power(int y){
    double tmp=1;double x=p-1.0;//注意类型
    while(y){
        if(y&1) tmp*=x;
        x*=x;
        y>>=1;
    }
    return tmp;
}
int main(){
    while(scanf("%d %lf",&n,&p)!=EOF){
        for(int i=1;i<=n;++i) scanf("%d",&x[i]);
        ans=1;x[0]=0;
        sort(x+1,x+1+n);//原来的地雷不一定有序
        for(int i=1;i<=n;++i){
            int tmp=x[i]-x[i-1]-1;//走到地雷前
            ans*=((1.0-power(tmp))/(2.0-p));
            if(fabs(ans)<1e-8) break;//为0直接退出
            ans*=(1.0-p);//跳过地雷,走两步
        }
        printf("%.7lf\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/donkey2603089141/p/11803226.html