矩阵快速幂
写在前面的话:这个东西自学的,所以不大会, 错误的地方敬请指出。
前置知识
快速幂
放个模板
template <class T>
T power (T a, int b) {
T res = 1;
for (; b; b >>= 1, a *= a) {
if (b & 1) {
res *= a;
}
}
return res;
}
因为比较简单,就不讲了。。。(其实是太懒。
一些东西
矩阵就是一个二位数组, 对于加法减法只需要直接计算就可以了。
运算
乘法
特殊一点的是乘法。 \(c_{i, j} = \sum^n_{k=1}a_{i,k}\times b_{k,j}\)
代码比较简单
#define vec std::vector<i64>
#define mat std::vector<vec>
std::function<mat(mat, mat)> mul = [&](mat a, mat b) {
mat res(n, vec(n));
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
res[i][j] = (res[i][j] + a[i][k] * b[k][j] % P) % P;
}
}
}
return res;
};
快速幂
矩阵求快速幂也是很简单,只需要把乘号替换成上面的那个东西就可以了。
std::function<mat(mat, i64)> power = [&](mat a, i64 k) {
mat res(n, vec(n));
// 定义单位矩阵
for (int i = 0; i < n; i++) {
res[i][i] = 1;
}
while (k) {
if (k & 1) {
res = mul(res, a);
}
a = mul(a, a);
k >>= 1;
}
return res;
};
原因
可以发现,使用矩阵快速幂把递推的计算变成了乘的计算。
从某种意义上来说加速了递推的速度,比如把求斐波那契数列的第 \(n\) 项时间复杂度为 \(O(n)\) 变成 \(O(log\ n)\) 的神奇加速。