矩阵的定义:
矩阵就用二维数组存储,在结构体中也保存了矩阵的行数、列数 (m、n)。
在矩阵之间的计算中需要行数和列数的信息,与其在用到时指定,不如和矩阵二维数组一同放在结构体内,初始化时赋值。
把初始化的构造函数放在结构体内,就不用在外部使用前每次手动初始化,很方便。
由于经常要用到矩阵相乘,就直接重载了 * ,不用每次调用函数。
#include <memory.h>
typedef long long ll;
const int MOD = 1e9+7;
const int MAXN = 3;
struct mat {
ll c[MAXN][MAXN];
int m, n; //表示矩阵的行数、列数
mat(int a, int b) : m(a), n(b) { //构造函数初始化
memset(c, 0, sizeof(c));
}
mat operator * (const mat& temp) { //重载运算符 *
mat ans(m, temp.n);
for (int i = 0; i < m; i ++)
for (int j = 0; j < temp.n; j ++)
for (int k = 0; k < n; k ++)
ans.c[i][j] = (ans.c[i][j] + c[i][k] * temp.c[k][j] % MOD) % MOD;
return ans;
}
};
矩阵快速幂:
求矩阵的幂时,也有快速幂计算,这里可以参考普通的快速幂算法。复杂度为
mat mat_pow(mat M, int n) { //矩阵快速幂
mat ans(M.m, M.m);
for (int i = 0; i < M.m; i ++)
ans.c[i][i] = 1;
while (n > 0) {
if (n & 1) ans = ans * M;
M = M * M;
n >>= 1;
}
return ans;
}
应用:
在求递推公式时很好用。就拿最简单的斐波那契数列举例,该数列满足:
若要求第 项时,显然直接递推是不实际的。这里应该借助矩阵来做,把递推公式改写成如下:
因此,可以推出
所以只需要用矩阵快速幂求出 便可很快地求出结果。
挑战上总结了更为一般的情况:
举个例子,好理解一些:
改写成矩阵递推公式就是
送一题:https://blog.youkuaiyun.com/Originum/article/details/82111066