zoukankan      html  css  js  c++  java
  • TOJ---3492---矩阵快速幂

    第一次做矩阵快速幂 先讲下矩阵快速幂的基础  矩阵乘法 --

    进行 矩阵A(M * N) B(P * Q) 相乘 满足的条件 -----> N==P  然后 相乘得到 C(M * Q)

    矩阵乘法也属于线形代数那快 ----  虽然我还没学 =-=

    但一般 都是满足乘法结合律 和 交换律的

    但这里 只满足 结合律 -> (A*B)*C == A*(B*C) 

    而不满足 交换律 就拿刚刚上面的矩阵 A B来说吧 A * B != B * A 即便就在(M == Q) 但要是矩阵内的元素值很特殊 那就另说了~

    当你用到 矩阵快速幂的时候 会有一个 很特殊的矩阵 它的作用很大-- 单位矩阵-主对角线(从左上角->右下角)初始值为1 其余地方 初始值为0

    它的作用类似于你进行一系列乘法运算将一个存储的值 初始化为1 和进行一系列加法运算将一个存储的值 初始化为0

    进行 矩阵快速幂运算的时候 主要运用到了 二进制 的思想 --- 就是将求的 幂的次数 拆分成2进制数后 然后在为1的位置下 进行相加

    15 -- 1111  8 + 4 + 2 + 1

    关于这种运用二进制的拆分 我还能想到在 多重背包的时候 我们也会涉及 - > 大大耗子 讲的

    这个的拆分 代码 应该是核心模块吧

    while( n )
    {
        if( n&1 )
        {
            res = multiply( res , base ); // 这里的这个函数名 multiply 就是乘法的意思
        }
        base = multiply(  base , base );
    }
    View Code

    然后 就 上题目吧

      touch me

    关于这题 一定要看清题目和反应过来

    当时 我很stupid地 纠结在  怎么求fib(n)的最后4位呢?   读了好几遍题目才发现  它要求我们进行对 10000 求模的 =-=

    还有我在想 我们得到的那个 2 X 2的矩阵里 怎么找到fib(n)呢? 也是long long才发现 它起初给我们的式子中就包含了 fib(n)的位置 分别是[1][0] 与 [0][1]

    last 。。  贴 代码

     1 #include <iostream>
     2 using namespace std;
     3 
     4 const int mod = 10000;
     5 const int size = 2;
     6 
     7 struct matrix
     8 {
     9     int m[size][size];
    10 }result, base;
    11 
    12 matrix multiply( matrix a, matrix b )
    13 {
    14     matrix temp;
    15     for( int i = 0 ; i<size ; i++ )
    16     {
    17         for( int j = 0 ; j<size ; j++ )
    18         {
    19             temp.m[i][j] = 0;
    20             for( int k = 0 ; k<size ; k++ )
    21                 temp.m[i][j] = (temp.m[i][j] + a.m[i][k] * b.m[k][j]) % mod;
    22         }
    23     }
    24     return temp;
    25 }
    26 
    27 int fastMod(int n)
    28 {
    29     base.m[0][0] = base.m[0][1] = base.m[1][0] = 1;
    30     base.m[1][1] = 0;
    31     for( int i = 0 ; i<size ; i++ )
    32     {
    33         for( int j = 0 ; j<size ; j++ )
    34         {
    35             if( i==j )
    36                 result.m[i][j] = 1;
    37             else
    38                 result.m[i][j] = 0;
    39         }
    40     }
    41     while(n)
    42     {
    43         if( n&1 ) 
    44         {
    45             result = multiply( result , base );
    46         }
    47         base = multiply( base , base );
    48         n>>= 1;
    49     }
    50     return result.m[1][0];
    51 }
    52 
    53 int main()
    54 {
    55     int n;
    56     while( ~scanf("%d", &n) && n!=-1 )
    57     {   
    58         printf( "%d
    ",fastMod(n) );
    59     }
    60     return 0;
    61 }
    View Code

    学习于: 可笑痴狂 Amazing Y 博客园

    你可以在他们那边 学到更多  我这只是 自己用来 温习的 =-=

    次饭去了 2点了 饿死了 ~

    just follow your heart
  • 相关阅读:
    C#中Dictionary的用法
    System.Timers.Timer用法
    C#中的异步调用及异步设计模式(三)——基于事件的异步模式
    C#中的异步调用及异步设计模式(二)——基于 IAsyncResult 的异步设计模式
    C#中的异步调用及异步设计模式(一)
    [你必须知道的异步编程]——异步编程模型(APM)
    strncasecmp与strcasecmp用法
    C语言之strrchr函数
    HDU 5289 Assignment (ST算法区间最值+二分)
    poj 1733 Parity game(种类并查集)
  • 原文地址:https://www.cnblogs.com/radical/p/3802527.html
Copyright © 2011-2022 走看看