矩阵快速幂

写在前面的话:这个东西自学的,所以不大会, 错误的地方敬请指出。

前置知识

快速幂

放个模板

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)\) 的神奇加速。

posted @ 2022-03-17 12:52  落花月朦胧  阅读(51)  评论(1编辑  收藏  举报