Forever Young

洛谷 P3390 【模板】矩阵快速幂

思路

显然,这是一道矩阵快速幂模板题

矩阵快速幂是一个重要的东西,在许多题中可以找出转移矩阵,然后用矩阵快速幂加速,从而达到可以被接受的复杂度。

若两个矩阵可以相乘,当且仅当他们之中一个矩阵的行数等于另一个矩阵的列数,设\(A\)\(n\times k\) 矩阵,\(B\)\(k \times m\) 矩阵,则他们的乘积 \(C\)\(n\times m\) 矩阵,有公式 \(C_{i,j}=\sum\limits_{l=1}^k A_{i,l}\times B_{l, j}\)

在这里还要注意要有一个单位矩阵,这个单位矩阵是干什么的呢?其实就是一个非 \(0\)\(1\) 的正方形矩阵,左上角到右下角对角线上的数为 \(1\),其他地方都为 \(0\),一个矩阵与单位矩阵相乘,得到的结果还是这个矩阵,相当于一个数的乘 \(1\) 操作。

说完矩阵乘法和单位矩阵,就可以做这个题了,定义矩阵结构体,并重载矩阵相乘的 \(*\) 号运算符,就可以进行矩阵的快速幂操作,和普通快速幂差不多,原理也相似,不懂可以看代码,如果看不明白我写的,那么推荐这篇题解

代码

/*
  Name: P3390 【模板】矩阵快速幂
  Author: Loceaner
  Date:
  Description: 
  Debug: 不要在结构体里开数组开的太大 
         矩阵记得初始化 
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;

const int A = 1e2 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

inline int read() {
  char c = getchar();
  int x = 0, f = 1;
  for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
  for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return x * f;
}

int n, k;
struct matrix { 
  int a[A][A];
  matrix() { memset(a, 0, sizeof(a)); } 
  void init() { for (int i = 1; i <= n; i++) a[i][i] = 1; }
} a, ans;

matrix operator * (const matrix &x, const matrix &y) {
  matrix ans;
  for (int k = 1; k <= n; k++)
    for (int i = 1; i <= n; i++)
      for (int j = 1; j <= n; j++)
        ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod;
  return ans;
}

inline void power() {
  while (k) {
    if (k & 1) ans = ans * a;
    a = a * a, k >>= 1;
  }
}

signed main() { 
  n = read(), k = read();
  for (int i = 1; i <= n; i++) 
    for (int j = 1; j <= n; j++)
      a.a[i][j] = read();
  ans.init();
  power();
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++)
      cout << ans.a[i][j] << " ";
    puts("");
  }
  return 0;
}
posted @ 2019-05-17 11:12  Loceaner  阅读(1538)  评论(0编辑  收藏  举报