矩阵及矩阵快速幂

1 矩阵

矩阵是一个二维数组, 行数通常用 r o w row row r r r表示, 列数用 c o l u m n column column c c c表示, 矩阵由中括号或小括号括起来, 就像这样
( 1 2 3 4 5 6 7 8 9 ) \left( \begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{matrix} \right) 147258369
[ 1 2 3 4 5 6 7 8 9 ] \left[\begin{matrix}1 & 2 & 3 \\4 & 5 & 6 \\7 & 8 & 9\end{matrix}\right] 147258369
称左上到右下的一条对角线为主对角线

1.1 简单矩阵运算

矩阵加减: 两个行列数相等的矩阵进行运算, 对应位置的数值相加减
矩阵数乘: 一个矩阵与一个数字相乘, 矩阵中每个位置上的数都乘这个数字

1.2 矩阵乘法

一个长 a a a b b b的矩阵 X X X乘一个长 b b b c c c的矩阵 Y Y Y, 得到长 a a a c c c的矩阵 Z Z Z
Z i j = X {Z_i}_j = X Zij=X i i i行的数与 Y Y Y j j j行的数依次相乘, 也就是 Z i j = ∑ k = 1 b X i k + Y k j {Z_i}_j = \displaystyle \sum_{k=1}^b{{X_i}_k + {Y_k}_j} Zij=k=1bXik+Ykj
矩阵乘法不满足交换律 A × B ≠ B × A A \times B \ne B \times A A×B=B×A, 满足结合律 ( A × B ) × C = A × ( B × C ) (A \times B) \times C = A \times (B \times C) (A×B)×C=A×(B×C)

2 单位元

在一个运算系统中m 如果某个元素 x x x和一个元素 y y y做运算, 结果为 y y y, 称 x x x为这个运算系统的单位元
x x x运算 y = y y = y y=y时称 x x x左单位元, y y y运算 x = y x = y x=y时称 x x x右单位元
特殊地, 当满足交换律时: x x x运算 y = y y = y y=y运算 x = y x = y x=y, 称 x x x双边单位元

3 矩阵快速幂

先看一个普通快速幂代码

int qpow(int x, int y){
	int res = 1;
	while(y){
		if(y & 1)	res = res * x;
		y >>= 1;
		x = x * x;
	}
	return res;
}

在这个代码中 r e s res res赋的初值 1 1 1, 就是乘法运算中的单位元
那我们就不难想象所有运算中的快速幂都可以用这个代码, 只需要把 r e s res res的初值赋为该运算系统的单位元

3.1 单位元矩阵

设四个数 a , b , c , d a, b, c, d a,b,c,d

[ 1 2 3 4 ] × [ a b c d ]   = [ 1 2 3 4 ] \left[\begin{matrix}1 & 2 \\ 3 & 4\end{matrix}\right] \times \left[\begin{matrix}a & b \\ c & d\end{matrix}\right] \,= \left[\begin{matrix}1 & 2 \\ 3 & 4\end{matrix}\right] [1324]×[acbd]=[1324]

得到
{ a + 2 c = 1 b + 2 d = 2 3 a + 4 c = 3 3 b + 4 d = 4 \begin{cases} a+2c = 1 \\ b+2d = 2 \\ 3a+4c = 3 \\ 3b + 4d = 4 \end{cases} a+2c=1b+2d=23a+4c=33b+4d=4

解得
{ a = 1 b = 0 c = 0 d = 1 [ 1 0 0 1 ] \begin{cases} a = 1 \\ b = 0 \\ c = 0 \\ d = 1 \end{cases} \qquad\left[ \begin{matrix} 1 & 0 \\ 0 & 1 \\ \end{matrix} \right] a=1b=0c=0d=1[1001]

三维矩阵解得
[ 1 0 0 0 1 0 0 0 1 ] \left[ \begin{matrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{matrix} \right] 100010001

发现单位元矩阵主对角线的数字为 1 1 1, 其他位置为 0 0 0, 我们一般称 单位元矩阵 为单位矩阵

3.2 例题

求斐波那契数列的第 n n n ( 1 ≤ n ≤ 2 63 − 1 ) (1 \le n \le 2^{63}-1) (1n2631), 可以构造一个矩阵 A A A, 使矩阵 [ a n − 1 a n − 2 0 0 ] × A = [ a n a n − 1 0 0 ] \left[\begin{matrix}a_{n-1} & a_{n-2} \\0 & 0\end{matrix}\right] \times A = \left[\begin{matrix}a_n & a_{n-1} \\0 & 0\end{matrix}\right] [an10an20]×A=[an0an10]
这样通过 [ a 2 a 1 0 0 ] × A n − 2 \left[\begin{matrix}a_2 & a_1 \\0 & 0\end{matrix}\right] \times A^{n-2} [a20a10]×An2得到 [ a n a n − 1 0 0 ] \left[\begin{matrix}a_n & a_{n-1} \\0 & 0\end{matrix}\right] [an0an10]
计算得到 A = [ 1 1 1 0 ] A = \left[\begin{matrix}1 & 1 \\1 & 0\end{matrix}\right] A=[1110]

4 矩阵模板

struct Matrix{
	int a[N][N];
	int r, c;
	// 构造函数 函数名与结构体名相同 无返回值 
	Matrix(int _r = 0, int _c = 0){
		r = _r, c = _c;
		memset(a, 0, sizeof(a));
		if(c == 0)
			c = r; // 如果只传递r的值, 矩阵变成方阵 
	}
	// 单位矩阵 
	void unit(){
		memset(a, 0, sizeof(a));
		for(int i = 1;i <= r;i++)
			a[i][i] = 1;
	}
	Matrix operator+(const Matrix &t) const{
		Matrix ans(r, c);
		for(int i = 1;i <= r;i++)
			for(int j = 1;j <= c;j++)
				ans.a[i][j] = a[i][j] + t.a[i][j];
		return ans;
	}
	Matrix operator-(const Matrix &t) const{
		Matrix ans = *this; //*this表示直接复制当前结构内容 
		for(int i = 1;i <= r;i++)
			for(int j = 1;j <= c;j++)
				ans.a[i][j] -= t.a[i][j];
		return ans;
	}
	Matrix operator*(const int &t) const{
		Matrix ans = *this;
		for(int i = 1;i <= r;i++)
			for(int j = 1;j <= c;j++)
				ans.a[i][j] *= t;
		return ans;
	}
	Matrix operator*(const Matrix &t) const{
		Matrix ans(r, t.c);  //r行c列乘以t.r行t.c列
		int n = r, m = t.c;
		for(int i = 1;i <= n;i++)
			for(int j = 1;j <= m;j++)
				for(int k = 1;k <= c;k++)
					ans.a[i][j] += a[i][k] * t.a[k][j];
		return ans;
	}
	Matrix operator%(const int t) const{
		Matrix ans = *this;
		for(int i = 1;i <= r;i++)
			for(int j = 1;j <= c;j++)
				ans.a[i][j] %= t;
		return ans;
	}
	void print(){
		for(int i = 1;i <= r;i++){
			for(int j = 1;j <= c;j++)
				printf("%d ", a[i][j]);
			printf("\n");
		}
	}
	Matrix pow(ll b){
		// 计算b次方 
		Matrix ans(r, c), a = *this;
		ans.unit();
		while(b){
			if(b & 1)	ans = ans * a;
			a = a *a;
			b >>= 1;
		}
		return ans;
	}
	Matrix pow(ll b, ll p){
		//计算b次方模p 
		Matrix ans(r, c), a = *this;
		ans.unit();
		while(b){
			if(b & 1)	ans = ans * a % p;
			a = a * a % p;
			b >>= 1;
		}
		return ans;
	}
};
  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值