POJ3744——概率DP 矩阵快速幂优化——Scout YYF I

http://poj.org/problem?id=3744

矩阵快速幂:

利用DP的递推式

就本题来说 dp[i] = p*dp[i-1] + (1-p)*dp[i-2]

由于x非常大最大1亿,这样的话复杂度就为1亿

所以这里可以用矩阵的思想

[dp[i]   dp[i-1] ] = [ dp[i-1]  dp[i-2] ] | p   1 - p|

| 1      0  |

递推得到

n - 1

[dp[n]   dp[n-1]] = [dp[1]   dp[2] ] |p   1 - p|

|1      0 |

注意我这里分开了矩阵和行列式!!!

(由于忘了线代,纠结了四五天- - 一直以为最后一步还要做一次乘法)

题目说了第一步肯定走1 dp[1] = 1

然后就利用快速幂(只是把矩阵相乘用了这个思想优化)

11101

把所有乘法相当于变成了二进制,2^0 +2^2 + 2^3 + 2^4

如果有末尾1  那么乘上,每次把2自己翻倍

就是一开始 为2^0, 然后看见了最后这个1  总值*2^0      2^0 变成2^1

倒数第二个是0      总值还是原值    2*1 变成 2*2

......

要排序一下

这里注意当a[i] == a[i-1] 会出现幂为负数的情况,因为我这里写的是while(n) 这样就会出现死循环T了- - 特判掉。

还有最后输出要.7f..WA了

/************************************************
* Author        :Powatr
* Created Time  :2015-8-31 13:16:26
* File Name     :B.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;

struct Matrix
{
    double a[2][2];
    void inti(){
        a[0][0] = a[1][1] = 1;
        a[1][0] = a[0][1] = 0;
    }
};
Matrix mul(Matrix a, Matrix b)
{
    Matrix ans;
    for(int i = 0 ; i < 2; i++){
        for(int j = 0; j < 2; j++){
           ans.a[i][j] = 0;
           for(int k = 0 ; k < 2; k++){
               if(a.a[i][k] == 0 || b.a[k][j] == 0) continue;
              ans.a[i][j] += a.a[i][k]*b.a[k][j];
           }
        }
    }
    return ans;
} 

Matrix pow_m(Matrix a, int n)
{
    Matrix ans;
    ans.inti();
    while(n){

        if(n&1) ans = mul(ans, a);
        n >>= 1;
        a = mul(a, a);
    }
    return ans;
}
double dp[11];
int b[11];
int main(){
    int n;
    double p;
    Matrix matrix;
    Matrix ret;
    while(~scanf("%d%lf", &n, &p)){
        double sum = 1;
        for(int i = 1; i <= n; i++)
            scanf("%d", &b[i]);
        sort(b + 1, b + n + 1);
                matrix.a[0][0] = p;
                matrix.a[0][1] = 1 - p;
                matrix.a[1][0] = 1;
                matrix.a[1][1] = 0;

        ret = pow_m(matrix, b[1] - 1);
        dp[1] = ret.a[0][0];
        sum *= (1 - dp[1]);
        for(int i = 2; i <= n; i++){
            if(b[i] == b[i-1]) continue;
            ret = pow_m(matrix, b[i] - b[i-1]- 1);
            dp[i] = ret.a[0][0];
            sum *= (1 - dp[i]);
        }
        printf("%.7f\n", sum);
    }
    return 0;
}

  

时间: 2024-10-21 10:41:35

POJ3744——概率DP 矩阵快速幂优化——Scout YYF I的相关文章

poj 3744 概率dp 矩阵快速幂优化

一位童子兵要穿过一条路,路上有些地方放着地雷.这位童子兵非常好玩,走路一蹦一跳的.每次他在 i 位置有 p 的概率走一步到 i+1 ,或者 (1-p) 的概率跳一步到 i+2.童子兵初始在1位置,求他安全通过这条道路的概率. 以所在位置为状态,dp[i] 表示在位置 i 的安全的概率. dp[i] = p * dp[i-1] + (1 - p) * dp[i-2]; // i 位置没有地雷 但是题目数据的范围是 10^8 这样dp的话会 TLE. 想想可以用矩阵快速幂优化.简单退出矩阵是 |p

[poj3744]Scout YYF I(概率dp+矩阵快速幂)

题意:在一维空间上存在一些雷,求安全通过的概率.其中人有$p$的概率前进一步,$1-p$的概率前进两步. 解题关键:若不考虑雷,则有转移方程:$dp[i] = p*dp[i - 1] + (1 - p)*dp[i - 2]$ 由于雷的数量很少,所以可以以雷为界,将区域分开,在每个区域中,通过该段的概率等于1-踩到该段终点的地雷的概率.然后用矩阵快速幂优化一下即可 1 #include<cstdio> 2 #include<cstring> 3 #include<algorit

poj 3744 Scout YYF I (概率DP+矩阵快速幂)

Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5062   Accepted: 1370 Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's base. After overcoming a series difficulties, YYF is now

POJ 3744 Scout YYF I (概率DP+矩阵快速幂)

题意:小明要从1走过一段直线雷区,给定n个地雷的坐标,他走一步的概率是p,两步的概率为1-p,问你他能安全通过雷区的概率. 析:很明显这是一个概率DP,用d(i)表示到达 i 时他安全的概率,那么d[i] = p * d[i-1] + (1-p) * d[i-2];这个状态转移方程很好理解, 就是说要想到达 i 要么从第 i-1 走一步,要么从 i-2 走两步,最后加起来,然后问题来了,这个数可能达到 1E8,那么时间空间复杂度都受不了, 观察这个状态转移方程,是不是很像Fibnacci数列,所

Scout YYF I POJ - 3744(概率dp + 矩阵快速幂)

题意: 一条路上有n个地雷,你从1开始走,单位时间内有p的概率走一步,1-p的概率走两步,问安全通过这条路的概率 解析: 很容易想到 dp[i] = p * dp[i-1] + (1 - p) * dp[i]; 然而...t,但这个式子明显可以用矩阵快速幂加个氮气一下加速一下... 把所有的点输入之后 sort一下,那么就能把这条路分成很多段 每一段以地雷为分界线 1 - x[0]  x[0]+1 - x[1]  x[1]+1 - x[2] ````````` 然后求出安全通过每一段的概率  

(POJ 3744)Scout YYF I(概率dp+矩阵快速幂)

概率dp入门题,转移方程为dp[i]=dp[i-1]*p+dp[i-2]*(1-p) 因为n个数字上限很大,所以常规的概率dp基本不可能,要用矩阵优化. 把路程分成n+1段,分别计算通过每段的成功率,即刚好跨越地雷的概率(dp[地雷x+1]) 算好每段之后把每段的成功率相乘. (若有两颗地雷相邻那么成功率是0) #include<iostream> #include<cstdio> #include<vector> #include<set> #includ

poj 3744 概率dp+矩阵快速幂

题意:在一条布满地雷的路上,你现在的起点在1处.在N个点处布有地雷,1<=N<=10.地雷点的坐标范围:[1,100000000]. 每次前进p的概率前进一步,1-p的概率前进1-p步.问顺利通过这条路的概率.就是不要走到有地雷的地方. 设dp[i]表示到达i点的概率,则 初始值 dp[1]=1. 很容易想到转移方程: dp[i]=p*dp[i-1]+(1-p)*dp[i-2]; 但是由于坐标的范围很大,直接这样求是不行的,而且当中的某些点还存在地雷. N个有地雷的点的坐标为 x[1],x[2

POJ-3744ScoutYYFI[概率DP][矩阵快速幂]

534禄DTJ蓝厍7簿L返http://www.zcool.com.cn/collection/ZMTgyMzIyNzI=.html 未导IU48lXF侥渍幕http://www.zcool.com.cn/collection/ZMTgyMzIzNjA=.html O1k澳4匀siy扯饲uhttp://www.zcool.com.cn/collection/ZMTgyMzIzODg=.html G3U8w2cs0y2http://www.zcool.com.cn/collection/ZMTgy

POJ3735 Training little cats DP,矩阵快速幂,稀疏矩阵优化

题目大意是,n只猫,有k个动作让它们去完成,并且重复m次,动作主要有三类gi,ei,s i j,分别代表第i只猫获得一个花生,第i只猫吃掉它自己所有的花生,第i只和第j只猫交换彼此的花生.k,n不超过100,m不超过1000,000,000,计算出最后每只猫还剩下多少个花生. 我们假设一个n维向量P,每个分量的值代表这n只猫所拥有的花生数,那么对于gi操作其实就是在第i维分量上加上1:对于ei,那就是在第i维分量上乘以0,说到这里,有木有感觉这很像3D坐标转化中的平移矩阵和缩放矩阵?没错,就是这