现在的位置: 首页 > 综合 > 正文

POJ 3744 Scout YYF I 简单递推

2018年03月17日 ⁄ 综合 ⁄ 共 946字 ⁄ 字号 评论关闭

题意就是

一个人, 站在坐标为1的点处,然后每次走路有p的概率一下走出去坐标1,1-p的概率一下走出去坐标2

路上某些点(n < 10)有雷,问这个人最终迈过这些雷不被炸的概率是多大

想一下就知道这些雷之间实际上是独立不相关的

可以分段考虑

然后互相之间乘一下就行

假设有个雷在x点

现在人在坐标1

然后不踩雷就得从1点到x-1点

并且从x-1点迈出坐标2到x+1

从x-1迈出坐标2到x+1的概率是1-p

之前1到x-1这段是没有任何雷的。就可以进行普通的递推了

a_n = a_(n-1) * p + a_(n-2) * (1-p)

这个我们可以用矩阵乘法

或者求出通项

a_n - a_(n-1) * p -a_(n-2) * (1-p) = 0

特征方程是n^2 - p *n - (1-p) = 0

求出两个解,1, p - 1

a_n = A + B * (p - 1) ^ n

带入a_0 = 1 , a_1 = p

得a_n = 1/(2-p) + (1-p) / (2-p) * (p - 1 ) ^n

即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
#include <ctime>
#define MAXN 222222
#define MAXM 222222
#define INF 1000000001
using namespace std;
double p;
int n;
int a[15];
double ans;
double getan(int x) {
    return 1.0 / (2.0 - p) + (1.0 - p) / (2.0 - p) * pow(p - 1.0, x);
}
int main() {
    while(scanf("%d%lf", &n, &p) != EOF) {
        for(int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
        }
        sort(a, a + n);
        int now = 1;
        ans = 1;
        for(int i = 0; i < n; i++) {
            int nxt = a[i];
            if(a[i] >= now + 1) {
                int dis = a[i] - now - 1;
                ans = ans * getan(dis) * (1.0 - p);
                now = a[i] + 1;
            } else {
                ans = 0;
                break;
            }
        }
        printf("%.7f\n", ans);
    }
    return 0;
}

抱歉!评论已关闭.