• 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
    ", sum);
        }
        return 0;
    }
    

      

  • 相关阅读:
    C# 事件的简单例子
    pl sql 的目录 所在的目录 不能有 小括号,如 Program Files (x86)
    转】 C# 图片格式(JPG,BMP,PNG,GIF)等转换为ICO图标
    TQQ2440第三节:串口
    今天发现一个bug,不知道是什么问题,printf的问题吗,还是什么。先记下!
    【转载】内存对齐详解
    TQQ2440第二节:流水灯
    TQQ2440第一节:启动代码
    wince下sources\sources.cmn\Makefile.def的相关作用
    (基于Java)编写编译器和解释器第10章:类型检查第一部分
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4772937.html
Copyright © 2020-2023  润新知