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 }
  • 相关阅读:
    状压DP【p1879】[USACO06NOV]玉米田Corn Fields
    Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划
    Tarjan缩点【p1726】上白泽慧音
    分层图【p4822】[BJWC2012]冻结
    Tarjan缩点+LCA【p2783】有机化学之神偶尔会做作弊
    线段树【p1607】[USACO09FEB]庙会班车Fair Shuttle
    better-scroll踩坑合集
    在浏览器上安装 Vue Devtools工具
    无法执行vue初始化命令
    vue-cli创建第一个项目(用git bash解决上下键移动选择问题)
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/12313945.html
Copyright © 2011-2022 走看看