矩阵快速幂

矩阵快速幂

对于方阵 M M M,在计算其 n n n 次幂 M n M^n Mn 时,传统的做法是,依次将 n n n M M M 相乘,但是这样计算起来的效率并不高,时间复杂度为 O ( n ) O(n) O(n),而矩阵快速幂可以加速矩阵幂的计算。

矩阵快速幂

原理
n n n 转为二进制, n = ( b k b k − 1 . . . b 2 b 1 b 0 ) 2 = b k ⋅ 2 k + b k − 1 ⋅ 2 k − 1 + . . . + b 2 ⋅ 2 2 + b 1 ⋅ 2 1 + b 0 ⋅ 2 0 n=(b_kb_{k-1}...b_2b_1b_0)_2=b_k\cdot 2^k+b_{k-1}\cdot 2^{k-1}+...+b_2\cdot 2^2+b_1\cdot 2^1+b_0\cdot 2^0 n=(bkbk1...b2b1b0)2=bk2k+bk12k1+...+b222+b121+b020,则
M n = M b k ⋅ 2 k + b k − 1 ⋅ 2 k − 1 + . . . + b 2 ⋅ 2 2 + b 1 ⋅ 2 1 + b 0 ⋅ 2 0 = M b k ⋅ 2 k ⋅ M b k − 1 ⋅ 2 k − 1 ⋅ . . . ⋅ M b 2 ⋅ 2 2 ⋅ M b 1 ⋅ 2 1 ⋅ M b 0 ⋅ 2 0 ⋅ M^n=M^{b_k\cdot 2^k+b_{k-1}\cdot 2^{k-1}+...+b_2\cdot 2^2+b_1\cdot 2^1+b_0\cdot 2^0}=M^{b_k\cdot 2^k}\cdot M^{b_{k-1}\cdot 2^{k-1}}\cdot ...\cdot M^{b_2\cdot 2^2}\cdot M^{b_1\cdot 2^1}\cdot M^{b_0\cdot 2^0}\cdot Mn=Mbk2k+bk12k1+...+b222+b121+b020=Mbk2kMbk12k1...Mb222Mb121Mb020

对于上面的式子,我们可以发现一些有用信息:

  • b i = 0    ( 0 ⩽ i ⩽ k ) b_i=0 \ \ (0\leqslant i\leqslant k) bi=0  (0ik),则 M b i ⋅ 2 i = 1 M^{b_i\cdot 2^i}=1 Mbi2i=1
  • ( M 2 i ) 2 = M 2 i + 1    ( 0 ⩽ i < k ) (M^{2^i})^2=M^{2^{i+1}} \ \ (0\leqslant i < k) (M2i)2=M2i+1  (0i<k)

计算过程

伪代码:

M n M^n Mn n = ( b k b k − 1 . . . b 2 b 1 b 0 ) 2 n=(b_kb_{k-1}...b_2b_1b_0)_2 n=(bkbk1...b2b1b0)2

  • r e s u l t = E (单位矩阵) result=\mathbb{E}\text{(单位矩阵)} result=E(单位矩阵)
  • ② 从低位到高位遍历 n n n 的二进制 ( b k b k − 1 . . . b 2 b 1 b 0 ) 2 (b_kb_{k-1}...b_2b_1b_0)_2 (bkbk1...b2b1b0)2
    • b i = 1    ( 0 ⩽ i ⩽ k ) b_i=1 \ \ (0\leqslant i\leqslant k) bi=1  (0ik) r e s u l t = r e s u l t ∗ M result=result*M result=resultM
    • M = M ∗ M M=M*M M=MM
  • ③ 遍历结束,返回 r e s u l t result result

示例:

M = [ 1 1 1 0 ] M=\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} M=[1110] n = 5 n=5 n=5,求 M n M^n Mn

  • r e s u l t = [ 1 0 0 1 ] result=\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} result=[1001]
  • ② 从低位到高位遍历 n n n 的二进制 b 2 b 1 b 0 = ( 101 ) 2 b_2b_1b_0=(101)_2 b2b1b0=(101)2
    • b 0 = 1 b_0=1 b0=1
      r e s u l t = r e s u l t ∗ M = [ 1 0 0 1 ] [ 1 1 1 0 ] = [ 1 1 1 0 ] result=result*M=\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}=\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} result=resultM=[1001][1110]=[1110] M = M ∗ M = [ 1 1 1 0 ] [ 1 1 1 0 ] = [ 2 1 1 1 ] M=M*M=\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}=\begin{bmatrix} 2 & 1 \\ 1 & 1 \end{bmatrix} M=MM=[1110][1110]=[2111]
    • b 1 = 0 b_1=0 b1=0
      M = M ∗ M = [ 2 1 1 1 ] [ 2 1 1 1 ] = [ 5 3 3 2 ] M=M*M=\begin{bmatrix} 2 & 1 \\ 1 & 1 \end{bmatrix}\begin{bmatrix} 2 & 1 \\ 1 & 1 \end{bmatrix}=\begin{bmatrix} 5 & 3 \\ 3 & 2 \end{bmatrix} M=MM=[2111][2111]=[5332]
    • b 2 = 1 b_2=1 b2=1
      r e s u l t = r e s u l t ∗ M = [ 1 1 1 0 ] [ 5 3 3 2 ] = [ 8 5 5 3 ] result=result*M=\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\begin{bmatrix} 5 & 3 \\ 3 & 2 \end{bmatrix}=\begin{bmatrix} 8 & 5 \\ 5 & 3 \end{bmatrix} result=resultM=[1110][5332]=[8553] M = M ∗ M = [ 5 3 3 2 ] [ 5 3 3 2 ] = [ 34 21 21 13 ] M=M*M=\begin{bmatrix} 5 & 3 \\ 3 & 2 \end{bmatrix}\begin{bmatrix} 5 & 3 \\ 3 & 2 \end{bmatrix}=\begin{bmatrix} 34 & 21 \\ 21 & 13 \end{bmatrix} M=MM=[5332][5332]=[34212113]
  • ③ 遍历结束,返回 r e s u l t = [ 8 5 5 3 ] result=\begin{bmatrix} 8 & 5 \\ 5 & 3 \end{bmatrix} result=[8553]

算法

vector<vector<int>> matrixMultiple(const vector<vector<int>>& left,const vector<vector<int>>& right){
	int leftRows=left.size();
	int count=left[0].size();
	int rightColumns=right[0].size();
	vector<vector<int>> result(leftRows,vector<int>(rightColumns));
	for(int i=0;i<leftRows;++i){
		for(int j=0;j<rightColumns;++j){
			for(int k=0;k<count;++k){
				result[i][j]+=(left[i][k]*right[k][j]);
			}
		}
	}
	return result;
};

vector<vector<int>> matrixQuickPow(vector<vector<int>> m,int n){		//求方阵m的n次幂
	int rows=m.size();
	vector<vector<int>> result(rows,vector<int>(rows));
	for(int i=0;i<rows;++i){
		result[i][i]=1;
	}
	while(n>0){
		if(n&1){
			result=matrixMultiple(result,m);
		}
		n>>=1;
		m=matrixMultiple(m,m);
	}
	return result;
}

复杂度分析

M n M^n Mn

  • 时间复杂度: O ( log ⁡ n ) O(\log n) O(logn),原本要进行 n − 1 n-1 n1 次矩阵乘法,使用矩阵快速幂后只用 log ⁡ 2 ( n ) \log_2(n) log2(n) 次。

矩阵快速幂的应用场景

有线性齐次递推式形如 f ( n ) = ∑ i = 1 m a i f ( n − i ) f(n) = \sum\limits_{i=1}^m a_if(n-i) f(n)=i=1maif(ni),我们就可以把这个递推式写成矩阵的形式,首先构造出一个矩阵 M M M,这是一个 m ∗ m m*m mm 的方阵,一般情况下,可以令
M = [ a 1 a 2 a 3 ⋯ a m − 1 a m 1 0 0 ⋯ 0 0 0 1 0 ⋯ 0 0 0 0 1 ⋯ 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ 0 0 0 ⋯ 1 0 ] M=\begin{bmatrix} a_{1} & a_{2} & a_{3} & \cdots & a_{m-1} & a_m\\ 1 & 0 & 0 & \cdots & 0 & 0\\ 0 & 1 & 0 & \cdots & 0 &0 \\ 0 & 0 & 1 & \cdots & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & 0 & \cdots & 1 &0 \end{bmatrix} M=a11000a20100a30010am10001am0000

然后可以得到 f ( n ) = ∑ i = 1 m a i f ( n − i ) f(n) = \sum\limits_{i=1}^m a_if(n-i) f(n)=i=1maif(ni) 的矩阵形式:
[ f ( n + 1 ) f ( n ) f ( n − 1 ) f ( n − 2 ) ⋮ f ( n − m ) ] = [ a 1 a 2 a 3 ⋯ a m − 1 a m 1 0 0 ⋯ 0 0 0 1 0 ⋯ 0 0 0 0 1 ⋯ 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ 0 0 0 ⋯ 1 0 ] [ f ( n ) f ( n − 1 ) f ( n − 2 ) f ( n − 3 ) ⋮ f ( n − m − 1 ) ] \begin{bmatrix} f(n+1) \\ f(n) \\ f(n-1) \\ f(n-2) \\ \vdots \\ f(n-m) \end{bmatrix}=\begin{bmatrix} a_{1} & a_{2} & a_{3} & \cdots & a_{m-1} & a_m\\ 1 & 0 & 0 & \cdots & 0 & 0\\ 0 & 1 & 0 & \cdots & 0 &0 \\ 0 & 0 & 1 & \cdots & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & 0 & \cdots & 1 &0 \end{bmatrix}\begin{bmatrix} f(n) \\ f(n-1) \\ f(n-2) \\ f(n-3) \\ \vdots \\ f(n-m-1) \end{bmatrix} f(n+1)f(n)f(n1)f(n2)f(nm)=a11000a20100a30010am10001am0000f(n)f(n1)f(n2)f(n3)f(nm1) = M [ f ( n ) f ( n − 1 ) f ( n − 2 ) f ( n − 3 ) ⋮ f ( n − m − 1 ) ] = M 2 [ f ( n − 1 ) f ( n − 2 ) f ( n − 3 ) f ( n − 4 ) ⋮ f ( n − m − 2 ) ] = . . . = M j + 1 [ f ( n − j ) f ( n − j − 1 ) f ( n − j − 2 ) f ( n − j − 3 ) ⋮ f ( n − j − m − 1 ) ] =M\begin{bmatrix} f(n) \\ f(n-1) \\ f(n-2) \\ f(n-3) \\ \vdots \\ f(n-m-1) \end{bmatrix}= M^2\begin{bmatrix} f(n-1) \\ f(n-2) \\ f(n-3) \\ f(n-4) \\ \vdots \\ f(n-m-2) \\ \end{bmatrix}=...= M^{j+1}\begin{bmatrix} f(n-j) \\ f(n-j-1) \\ f(n-j-2) \\ f(n-j-3) \\ \vdots \\ f(n-j-m-1) \\ \end{bmatrix} =Mf(n)f(n1)f(n2)f(n3)f(nm1)=M2f(n1)f(n2)f(n3)f(n4)f(nm2)=...=Mj+1f(nj)f(nj1)f(nj2)f(nj3)f(njm1)
若我们知道 [ f ( n − j ) f ( n − j − 1 ) f ( n − j − 2 ) f ( n − j − 3 ) ⋮ f ( n − j − m − 1 ) ] \begin{bmatrix} f(n-j) \\ f(n-j-1) \\ f(n-j-2) \\ f(n-j-3) \\ \vdots \\ f(n-j-m-1) \\ \end{bmatrix} f(nj)f(nj1)f(nj2)f(nj3)f(njm1) 的取值,就可以使用矩阵快速幂求出 M j + 1 M^{j+1} Mj+1,然后可以得到 [ f ( n + 1 ) f ( n ) f ( n − 1 ) f ( n − 2 ) ⋮ f ( n − m ) ] \begin{bmatrix} f(n+1) \\ f(n) \\ f(n-1) \\ f(n-2) \\ \vdots \\ f(n-m) \end{bmatrix} f(n+1)f(n)f(n1)f(n2)f(nm)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值