Loading

线性代数

矩阵

计算

加减法

将两个矩阵对应位置的元素相加减即可,两个矩阵的行,列数相等

满足交换律 \(A + B = B + A\) 和结合律 \((A + B) + C = A + (B + C)\)

乘法

  1. 一个数字 \(k\) 乘上矩阵 \(A\),把 \(A\) 中的所有元素都乘上 \(k\),记作 \(kA\)

  2. 矩阵 \(A\) 乘上矩阵 \(B\),要求 \(A\) 的列数等于 \(B\) 的行数,若 \(A\) 是一个 \(n \times k\) 的矩阵,\(B\) 是一个 \(k \times m\) 的矩阵,那么乘积 \(C\) 的大小就是 \(n \times m\)\(C_{i, j} = \sum \limits _ {p = 1} ^ k A_{i, p} \times B_{p, j}\)

for (int i = 1; i <= n; i++) {
  for (int j = 1; j <= m; j++) {
    for (int p = 1; p <= k; p++) {
      c[i][j] += a[i][p] * b[p][j];
    }
  }
}

满足结合律 \((A \times B) \times C = A \times (B \times C)\),但是不满足交换律。

单位矩阵

单位矩阵就是一个从左到右的对角线上的元素为 \(1\),其他地方的元素都为 \(0\) 的矩阵。

快速幂

首先,如果一个矩阵 \(A\) 可以快速幂,那么这个矩阵必须是 \(n \times n\) 的,也就是说,必须行数和列数相等。

而在前面,我们已经学会了矩阵乘法了,所以,剩下的操作就和快速幂是一样的了。

快速幂如果不会可以看这里 数论

struct matrix {
  int m[N][N];
  matrix operator * (const matrix &x) const {
    matrix ret;
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= n; j++) {
        ret.m[i][j] = 0;
      }
    }
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= n; j++) {
        for (int k = 1; k <= n; k++) {
          ret.m[i][j] = (ret.m[i][j] + 1ll * m[i][k] * x.m[k][j] % mod) % mod;
        }
      }
    }
    return ret;
  }
} a;

matrix P(matrix a, long long b) {
  matrix ret;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      ret.m[i][j] = 0;
    }
    ret.m[i][i] = 1;
  }
  while (b) {
    if (b & 1) {
      ret = ret * a;
    }
    a = a * a, b >>= 1;
  }
  return ret;
}

矩阵快速幂加速递推

洛谷 P1939

这道题给了一个递推式,但是 \(n\) 太大了,所以,我们可以考虑用矩阵快速幂加速递推。

首先,我们可以构造一个 \(1 \times 3\) 的矩阵 \(\begin{bmatrix} a_n, a_{n - 1}, a_{n - 2} \end{bmatrix}\),这个矩阵是由 \(\begin{bmatrix} a_{n - 1}, a_{n - 2}, a_{n - 3} \end{bmatrix}\) 乘上某个矩阵得到的,所以我们需要构造出这个加速递推的 \(3 \times 3\) 的矩阵 \(\begin{bmatrix} 1 & 1 & 0\\ 0 & 0 & 1 \\ 1 & 0 & 0 \end{bmatrix}\),再对这个矩阵做矩阵快速幂,最后输出即可。

#include <bits/stdc++.h>

using namespace std;

const int N = 10, mod = 1e9 + 7;

int T, n;

struct matrix {
  int m[N][N];
  matrix operator * (const matrix &x) const {
    matrix ret;
    for (int i = 1; i <= 3; i++) {
      for (int j = 1; j <= 3; j++) {
        ret.m[i][j] = 0;
      }
    }
    for (int i = 1; i <= 3; i++) {
      for (int j = 1; j <= 3; j++) {
        for (int k = 1; k <= 3; k++) {
          ret.m[i][j] = (ret.m[i][j] + 1ll * m[i][k] * x.m[k][j] % mod) % mod;
        }
      }
    }
    return ret;
  }
} a, b;

matrix P(matrix a, int b) {
  matrix ret;
  for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
      ret.m[i][j] = 0;
    }
    ret.m[i][i] = 1;
  }
  while (b) {
    if (b & 1) {
      ret = ret * a;
    }
    a = a * a, b >>= 1;
  }
  return ret;
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> T;
  while (T--) {
    cin >> n;
    a.m[1][1] = a.m[1][2] = a.m[2][3] = a.m[3][1] = 1, a.m[1][3] = a.m[2][1] = a.m[2][2] = a.m[3][2] = a.m[3][3] = 0;
    if (n < 3) {
      cout << 1 << '\n';
      continue;
    }
    a = P(a, n - 3);
    cout << ((a.m[1][1] + a.m[2][1]) % mod + a.m[3][1]) % mod << '\n';
  }
  return 0;
}

洛谷 P1349

这道题我们先构造一个 \(1 \times 2\) 的矩阵 \(\begin{bmatrix} a_n, a_{n - 1} \end{bmatrix}\),然后我们就可以构造出对应的 \(2 \times 2\) 的矩阵 \(\begin{bmatrix} p & 1 \\ q & 0 \end{bmatrix}\),再快速幂一下就可以了。

#include <bits/stdc++.h>

using namespace std;

const int N = 10;

int p, q, a1, a2, n, mod;

struct matrix {
  int m[N][N];
  matrix operator * (const matrix &x) const {
    matrix ret;
    for (int i = 1; i <= 2; i++) {
      for (int j = 1; j <= 2; j++) {
        ret.m[i][j] = 0;
      }
    }
    for (int i = 1; i <= 2; i++) {
      for (int j = 1; j <= 2; j++) {
        for (int k = 1; k <= 2; k++) {
          ret.m[i][j] = (ret.m[i][j] + 1ll * m[i][k] * x.m[k][j] % mod) % mod;
        }
      }
    }
    return ret;
  }
} a, b;

matrix P(matrix a, long long b) {
  matrix ret;
  for (int i = 1; i <= 2; i++) {
    for (int j = 1; j <= 2; j++) {
      ret.m[i][j] = 0;
    }
    ret.m[i][i] = 1;
  }
  while (b) {
    if (b & 1) {
      ret = ret * a;
    }
    a = a * a, b >>= 1;
  }
  return ret;
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> p >> q >> a1 >> a2 >> n >> mod;
  a.m[1][1] = p, a.m[1][2] = 1, a.m[2][1] = q, a.m[2][2] = 0;
  if (n == 1) {
    cout << a1;
    return 0;
  }
  a = P(a, n - 2);
  cout << (1ll * a.m[1][1] * a2 % mod + 1ll * a.m[2][1] * a1 % mod) % mod;
  return 0;
}
posted @ 2023-09-20 15:57  chengning0909  阅读(25)  评论(0编辑  收藏  举报