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

    矩阵相乘和快速幂基本模板

     1 typedef vector<int> vec;
     2 typedef vector<vec> mat;
     3 
     4 //计算A*B
     5 mat mul(mat &A, mat &B) {
     6     mat C(A.size(), vec(B[0].size()));
     7     for (int i = 0; i < A.size(); i++) {
     8         for (int k = 0; k < B.size(); k++) {
     9             for (int j = 0; j < B[0].size(); j++) {
    10                 C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD;
    11             }
    12         }
    13     }
    14     return C;
    15 }
    16 
    17 //计算A^n
    18 mat mat_pow(mat A, LL n) {
    19     mat B(A.size(), vec(A.size()));
    20     for (int i = 0; i < A.size(); i++) {
    21         B[i][i] = 1;
    22     }
    23     while (n > 0) {
    24         if (n & 1) B = mul(B, A);
    25         A = mul(A, A);
    26         n >>= 1;
    27     }
    28     return B;
    29 }

    POJ 3734 Blocks

    题意:

    N个方块排成一列,使用红蓝黄绿四种颜色给方块涂色,求染成后的红色方块和染成的绿色的方块的个数同时是偶数的方案总数,输出对10007取模后的答案

    解法:

    试着从左边开始一次染色,染到第i个方块为止,红绿都是偶数的方案数为$a_i$,红绿恰有一个是偶数的方案为$b_i$,红绿都有的方案为$c_i$, 这样,染到第i+1个方块的时候,红绿都是偶数的方案数有以下两种可能:

    1. 红绿都是偶数,且第i+1个为蓝色或黄色

    2. 红绿恰有一个为奇数,且第i+1个染成了奇数个对应的那种颜色

    那么有如下递推式:

    $a_{i+1}=2a_i+b_i$

    $b_{i+1}=2a_i+2b_i+2c_i$

    $c_{i+1}=b_i+2c_i$

    有一下矩阵式子:

    Ai+1      2 1 0   Ai

    Bi+1  =  2 2 2   Bi

    Ci+1      0 1 2   Ci

    等效于等号右边部分,左边的矩阵i次方,右边的为$a_0$,$b_0$, $c_0$

    快速幂求解。

    代码如下:

     1 typedef vector<int> vec;
     2 typedef vector<vec> mat;
     3 
     4 //计算A*B
     5 mat mul(mat &A, mat &B) {
     6     mat C(A.size(), vec(B[0].size()));
     7     for (int i = 0; i < A.size(); i++) {
     8         for (int k = 0; k < B.size(); k++) {
     9             for (int j = 0; j < B[0].size(); j++) {
    10                 C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD;
    11             }
    12         }
    13     }
    14     return C;
    15 }
    16 
    17 //计算A^n
    18 mat mat_pow(mat A, int n) {
    19     mat B(A.size(), vec(A.size()));
    20     for (int i = 0; i < A.size(); i++) {
    21         B[i][i] = 1;
    22     }
    23     while (n > 0) {
    24         if (n & 1) B = mul(B, A);
    25         A = mul(A, A);
    26         n >>= 1;
    27     }
    28     return B;
    29 }
    30 
    31 int N;
    32 
    33 void solve() {
    34     mat A(3, vec(3));
    35     A[0][0] = 2;
    36     A[0][1] = 1;
    37     A[0][2] = 0;
    38     A[1][0] = 2;
    39     A[1][1] = 2;
    40     A[1][2] = 2;
    41     A[2][0] = 0;
    42     A[2][1] = 1;
    43     A[2][2] = 2;
    44     // A = mat_pow(A, N);
    45     printf("%d
    ", A[0][0]);
    46 }
    47 
    48 int main() {
    49     scanf("%d", &N);
    50     solve();
    51     return 0;
    52 }
  • 相关阅读:
    linux下的mysql安装
    linux下解压zip文件
    解決eclipse 的alt + / 快捷鍵不好用
    linux 源代码目录结构
    Linux(ubuntu)下手动安装 firefox 6 并且添加快捷方式图标
    Ubuntu中配置Tomcat与Eclipse整合
    Linux下的tar压缩解压缩命令详解
    ubuntu创建、删除文件及文件夹,强制清空回收站方法
    九度-题目1011:最大连续子序列
    杭电1003-Max Sum
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/12313945.html
Copyright © 2011-2022 走看看