矩阵及矩阵优化杂谈

矩阵

一个 3×33\times 33×3 的矩阵 AAA:
A=∣110101010∣ A=\begin{vmatrix}1&1&0\\1&0&1\\0&1&0\end{vmatrix} A= 110101010

用 Ai,jA_{i,j}Ai,j 表示矩阵 AAA 的第 iii 行第 jjj 列,和二维数组差不多。

矩阵乘法

矩阵乘法

若一个 N×MN\times MN×M 的矩阵与一个 X×YX\times YX×Y 的矩阵相乘,前提条件是:M=XM=XM=X。即两个矩阵相乘,第一个矩阵的列数要与第二个矩阵的行数相等。

即需要一个 N×MN\times MN×M 的矩阵与 M×KM\times KM×K 的矩阵相乘。

若一个 N×MN\times MN×M 的矩阵 AAA 乘上 M×KM\times KM×K 的矩阵 BBB,记 C=A×BC=A\times BC=A×B。

则有:
Ci,j=∑k=1MAi,k×Bk,j C_{i,j}=\sum_{k=1}^{M}A_{i,k}\times B_{k,j} Ci,j=k=1∑MAi,k×Bk,j

如:
∣235∣×∣342∣=∣2×3+3×4+5×2∣=∣28∣ \begin{vmatrix}2&3&5\end{vmatrix}\times\begin{vmatrix}3\\4\\2\end{vmatrix}=\begin{vmatrix}2\times 3+3\times 4+5\times 2\end{vmatrix}=\begin{vmatrix}28\end{vmatrix} 235 × 342 = 2×3+3×4+5×2 = 28

一些特性

矩阵乘法中的 1

如果我们用一个 2×22\times 22×2 的矩阵 AAA 去乘上 ∣1001∣\begin{vmatrix}1&0\\0&1\end{vmatrix} 1001 ,你会发现得到的矩阵 BBB 与矩阵 AAA 是一样的。

一个 N×NN\times NN×N 的矩阵 CCC,满足 Ci,iC_{i,i}Ci,i 都是 1,其余都是 1,它在矩阵乘法中与数字乘法中 1 的作用相同。

没有交换律

A×B≠B×AA\times B\not= B\times AA×B=B×A,这在矩阵乘法中是成立的。


∣1221∣×∣2232∣=∣8676∣ \begin{vmatrix}1&2\\2&1\end{vmatrix}\times\begin{vmatrix}2&2\\3&2\end{vmatrix}=\begin{vmatrix}8&6\\7&6\end{vmatrix} 1221 × 2322 = 8766

但是
∣2232∣×∣1221∣=∣6678∣ \begin{vmatrix}2&2\\3&2\end{vmatrix}\times\begin{vmatrix}1&2\\2&1\end{vmatrix}=\begin{vmatrix}6&6\\7&8\end{vmatrix} 2322 × 1221 = 6768

所以,在矩阵乘法中,不存在交换律。

其实不用具体运算也能得到。

一个 N×MN\times MN×M 的矩阵与 M×KM\times KM×K 的矩阵相乘(N≠KN\not=KN=K),这显然是合法的,但是若交换,M×KM\times KM×K 的矩阵明显不能乘上 N×MN\times MN×M 的矩阵。

结合律

虽然 A×B=B×AA\times B=B\times AA×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)。

从合法性的角度来说,有:
(N×M)⋅(M×K)⋅(K×L)=(N×M)⋅[(M×K)⋅(K×L)]=(N×L) (N\times M)\cdot(M\times K)\cdot(K\times L)=(N\times M)\cdot[(M\times K)\cdot(K\times L)]=(N\times L) (N×M)⋅(M×K)⋅(K×L)=(N×M)⋅[(M×K)⋅(K×L)]=(N×L)

可以自己用几个矩阵来验证一下。

矩阵快速幂

快速幂

如果我们遇到需要求 abmod  pa^b\mod pabmodp,但是 bbb 特别大,如 101810^{18}1018,这时候肯定不能循环 bbb 次求了。

首先我们知道,使用 20,21,22,23,24⋯2^0,2^1,2^2,2^3,2^4\cdots20,21,22,23,24⋯ 可以通过加和组成任何正整数。

还知道 ab×ac=ab+ca^b\times a^c=a^{b+c}ab×ac=ab+c。

所以我们可以通过 a20,a21,a22,a23,a24⋯a^{2^0},a^{2^1},a^{2^2},a^{2^3},a^{2^4}\cdotsa20,a21,a22,a23,a24⋯ 相乘得到任何 aba^bab。

所以我们可以将 bbb 拆分成若干个 2 的次方相加。

同样的,这种快速求次方的方法也可以运用到其他运算,前提条件是其满足结合律。

矩阵快速幂

矩阵乘法也是一个满足结合律的运算。

有一个矩阵 A(N×N)A(N\times N)A(N×N),计算 A2kA^{2k}A2k,可以拆分成 Ak×AkA^k\times A^kAk×Ak。

数字中有 x0(x≠0)=1x^0(x\not=0)=1x0(x=0)=1,矩阵中也有矩阵 A0A^0A0 为矩阵乘法中的 1,即对角线为 1 的矩阵。

c++ 复制代码
#include<bits/stdc++.h>
#define int long long
#define endl putchar('\n')
#define psp putchar(' ')
using namespace std;
const int mod=1e9+7;
int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x*f;
}
void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x<10){putchar(x+'0');return;}
	print(x/10);
	putchar(x%10+'0');
}
void putstr(string s){
	for(int i=0;i<s.size();i++)putchar(s[i]);
}
int lowbit(int x){
	return x&-x;
}
int n,m,k;
int T;
int a[101][101];
int res[101][101];
int b[101][101];
void mul_res(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			b[i][j]=res[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			res[i][j]=0;
			for(int l=1;l<=n;l++){
				res[i][j]=(res[i][j]+a[i][l]*b[l][j]%mod)%mod;
			}
		}
	}
}
void mul_a(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			b[i][j]=a[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			a[i][j]=0;
			for(int l=1;l<=n;l++){
				a[i][j]=(a[i][j]+b[i][l]*b[l][j]%mod)%mod;
			}
		}
	}
}
signed main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			a[i][j]=read();
		}
	}
	for(int i=1;i<=n;i++)res[i][i]=1;
	while(k){
		if(k&1)mul_res();
		mul_a();
		k>>=1;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			print((res[i][j]+mod)%mod),psp;
		}
		endl;
	}
}

应用

形象化矩阵乘法

所以矩阵到底有什么用?

首先需要形象化矩阵乘法的过程。

先看一个 1×N1\times N1×N 的矩阵 AAA 乘上一个 N×1N\times 1N×1 的矩阵 BBB。
∣A1,1⋯A1,N∣×∣B1,1⋮BN,1∣ \begin{vmatrix}A_{1,1}&\cdots&A_{1,N}\end{vmatrix}\times\begin{vmatrix}B_{1,1}\\\vdots\\B_{N,1}\end{vmatrix} A1,1⋯A1,N × B1,1⋮BN,1

我们可以形象地理解为,将矩阵 AAA 竖起来,然后依次与矩阵 BBB 相乘。

如下图:

这样矩阵乘法就有了一种图像化的方法:先将第一个矩阵倒过来,再与第二个相乘。

现在解决了 (1×N)⋅(N×1)(1\times N)\cdot(N\times 1)(1×N)⋅(N×1) 的问题,接下来看 (1×N)⋅(N×M)(1\times N)\cdot(N\times M)(1×N)⋅(N×M) 的问题。

其实与单行的很类似,还是将第一个矩阵翻转过来,一列一列地计算就行了。

最后看到 (K×N)⋅(N×M)(K\times N)\cdot(N\times M)(K×N)⋅(N×M) 的计算。

我们可以将 K×NK\times NK×N 的矩阵拆分成 KKK 个 1×N1\times N1×N 的单行矩阵,这样又可以计算了。

应用 1

看一个简单的例子:计算 a+ba+ba+b。

我们构造一个矩阵 A=∣ab∣A=\begin{vmatrix}a&b\end{vmatrix}A= ab ,我们需要它们的和。

计算它们的和需要什么?需要第一个数和第二个数。

这个看似废话,实际就是废话。

然后我们看到最后的结果,a+ba+ba+b 的和是一个数,所以我们最终需要答案是一个 1×11\times 11×1 的矩阵。

构造的矩阵是 1×21\times 21×2 的,因此我们要乘上一个 2×12\times 12×1 的矩阵 BBB。

两者相乘,得到的结果是 ∣A1,1×B1,1+A1,2×B2,1∣\begin{vmatrix}A_{1,1}\times B_{1,1}+A_{1,2}\times B_{2,1}\end{vmatrix} A1,1×B1,1+A1,2×B2,1 。

将 A1,1=a,A1,2=bA_{1,1}=a,A_{1,2}=bA1,1=a,A1,2=b 带入:∣a×B1,1+b×B2,1∣\begin{vmatrix}a\times B_{1,1}+b\times B_{2,1}\end{vmatrix} a×B1,1+b×B2,1 。

我们需要的是 a+ba+ba+b,所以需要 B1,1=B2,1=1B_{1,1}=B_{2,1}=1B1,1=B2,1=1,所以 B=∣11∣B=\begin{vmatrix}1\\1\end{vmatrix}B= 11 。

应用 2

这一个应用可以推出矩阵乘法的最终奥义!

接下来的内容不着重于矩阵乘法的计算过程,如果有阅读困难请结合上文中形象化的矩阵乘法来理解。

计算斐波那契数列的第 nnn 位,但是 n≤1018n\le 10^{18}n≤1018。

我们用一个二元组 (x,y)(x,y)(x,y) 表示斐波那契数列的当前位和上一位。

如果我们要用二元组 (x,y)(x,y)(x,y) 推出下一个二元组是 (y,x+y)(y,x+y)(y,x+y)。

那么如果我们构造一个矩阵 A=∣xy∣A=\begin{vmatrix}x&y\end{vmatrix}A= xy 以表示上面二元组的信息,我们想要得到矩阵 ∣yx+y∣\begin{vmatrix}y&x+y\end{vmatrix} yx+y 。

首先,我们发现结果矩阵是 1×21\times 21×2 的,AAA 是 1×21\times 21×2 的,那么需要构造的乘数矩阵 BBB 应该是 2×22\times 22×2 的。

目前矩阵状态是这样的:
B=∣????∣ B=\begin{vmatrix}?&?\\?&?\end{vmatrix} B= ????

我们看到结果矩阵的第一位是 yyy,我们怎么用矩阵 AAA 得到 yyy?有:
y=x×0+y×1 y=x\times 0+y\times 1 y=x×0+y×1

所以我们可以得到矩阵 BBB 第一列中的数:
B=∣0?1?∣ B=\begin{vmatrix}0&?\\1&?\end{vmatrix} B= 01??

看到结果矩阵的第二个数,是 x+yx+yx+y,怎么得到?有:
x+y=x×1+y×1 x+y=x\times 1+y\times 1 x+y=x×1+y×1

所以可以得到完整的矩阵 BBB:
B=∣0111∣ B=\begin{vmatrix}0&1\\1&1\end{vmatrix} B= 0111

有:
∣xy∣×∣0111∣=∣yx+y∣ \begin{vmatrix}x&y\end{vmatrix}\times\begin{vmatrix}0&1\\1&1\end{vmatrix}=\begin{vmatrix}y&x+y\end{vmatrix} xy × 0111 = yx+y

我们构造最初的矩阵 AAA:
∣11∣ \begin{vmatrix}1&1\end{vmatrix} 11

现在我们要求斐波那契数列的第 nnn 位。我们令:
A′=A×Bn−2 A'=A\times B^{n-2} A′=A×Bn−2

此时的 A1,2′A'_{1,2}A1,2′ 就是斐波那契数列的第 nnn 位。

对于后面的 Bn−2B^{n-2}Bn−2 可以用矩阵快速幂提前计算出,由于结合律的存在,不会影响结果。

最后的时间复杂度就是 O(log⁡n)O(\log n)O(logn)。

推广 1

矩阵乘法虽然名字里有乘法,但是也可以加速加法的递推,如斐波那契数列,其递推式子本是:
febi=febi−1+febi−2 feb_i=feb_{i-1}+feb_{i-2} febi=febi−1+febi−2

但却可以转化成矩阵乘法。

我们不妨推广一下:若有递推式子:
dpi=dpi−1+2×dpi−2−dpi−3 dp_i=dp_{i-1}+2\times dp_{i-2}-dp_{i-3} dpi=dpi−1+2×dpi−2−dpi−3

如何转化成矩阵?

我们还是可以从相邻的状态转移开始。

定义矩阵:
A=∣xyz∣ A=\begin{vmatrix}x&y&z\end{vmatrix} A= xyz

矩阵 AAA 维护的信息有 dpi,dpi−1,dpi−2dp_i,dp_{i-1},dp_{i-2}dpi,dpi−1,dpi−2。

为什么没有维护 dpi−3dp_{i-3}dpi−3?

因为我们当前状态需要的只是 dpidp_idpi,若要推下一个状态,dpidp_idpi 就成了 dpi−1dp_{i-1}dpi−1,同理,dpi−2dp_{i-2}dpi−2 就是 dpi−3dp_{i-3}dpi−3 了。

然后看到转移。我们期望的下一步状态是:
∣x+2×y−zxy∣ \begin{vmatrix}x+2\times y-z&x&y\end{vmatrix} x+2×y−zxy

所以我们需要一个 3×33\times 33×3 的转移矩阵 BBB。

首先,我们需要结果的第一位是 x+2×y−zx+2\times y-zx+2×y−z。

因此,矩阵 BBB 的第一列出来了。
B=∣1??2??−1??∣ B=\begin{vmatrix}1&?&?\\2&?&?\\-1&?&?\end{vmatrix} B= 12−1??????

然后是第二列,我们只需要 xxx,所以对应 xxx 的位是 1,其余为 0。
B=∣11?20?−10?∣ B=\begin{vmatrix}1&1&?\\2&0&?\\-1&0&?\end{vmatrix} B= 12−1100???

第三列只要 yyy,与第二列同理。
B=∣110201−100∣ B=\begin{vmatrix}1&1&0\\2&0&1\\-1&0&0\end{vmatrix} B= 12−1100010

推广 2

如果我们的式子增加了一个常数:
dpi=dpi−1+dpi−2+1 dp_i=dp_{i-1}+dp_{i-2}+1 dpi=dpi−1+dpi−2+1

这时候我们在矩阵中加一个常数就行了。

定义当前矩阵:
∣xy1∣ \begin{vmatrix}x&y&1\end{vmatrix} xy1

目标状态:
∣x+y+1x1∣ \begin{vmatrix}x+y+1&x&1\end{vmatrix} x+y+1x1

看到转移。

对于第一列,有:x+y+1=x×1+y×1+1×1x+y+1=x\times 1+y\times 1+1\times 1x+y+1=x×1+y×1+1×1。

对于第二列,有:x=x×1+y×0+1×0x=x\times 1+y\times 0+1\times 0x=x×1+y×0+1×0。

对于第三列,有:1=x×0+y×0+1×11=x\times 0+y\times 0+1\times 11=x×0+y×0+1×1。

最终矩阵:
∣110100101∣ \begin{vmatrix}1&1&0\\1&0&0\\1&0&1\end{vmatrix} 111100001

推广 3

加一个变量,有递推式子:
dpn=dpn−1+dpn−2+n dp_n=dp_{n-1}+dp_{n-2}+n dpn=dpn−1+dpn−2+n

此时我们还是可以带一个 nnn,但是还需要多带一个常数 1,帮助 nnn 变成 n+1n+1n+1。

当前状态:
∣xyn1∣ \begin{vmatrix}x&y&n&1\end{vmatrix} xyn1

目标状态:
∣x+y+nxn+11∣ \begin{vmatrix}x+y+n&x&n+1&1\end{vmatrix} x+y+nxn+11

一列一列地讨论。

第一列:x+y+n=x×1+y×1+n×1+1×0x+y+n=x\times 1+y\times 1+n\times 1+1\times 0x+y+n=x×1+y×1+n×1+1×0

第二列:x=x×1+y×0+n×0+1×0x=x\times 1+y\times 0+n\times 0+1\times 0x=x×1+y×0+n×0+1×0

第三列:n+1=x×0+y×0+n×1+1×1n+1=x\times 0+y\times 0+n\times 1+1\times 1n+1=x×0+y×0+n×1+1×1

第四列:1=x×0+y×0+n×0+1×11=x\times 0+y\times 0+n\times 0+1\times 11=x×0+y×0+n×0+1×1

最终矩阵:
∣1100100010100011∣ \begin{vmatrix}1&1&0&0\\1&0&0&0\\1&0&1&0\\0&0&1&1\end{vmatrix} 1110100000110001

推广 4

式子:
dpi=dpi−1+dpi−2 dp_i=dp_{i-1}+dp_{i-2} dpi=dpi−1+dpi−2

但是同时需要维护前缀和:
Si=Si−1+dpi S_i=S_{i-1}+dp_i Si=Si−1+dpi

我们可以将 SiS_iSi 拆分:Si−1+dpi−1+dpi−2S_{i-1}+dp_{i-1}+dp_{i-2}Si−1+dpi−1+dpi−2

为什么要拆分?因为 dpidp_idpi 是不知道的, dpi−1,dpi−2dp_{i-1},dp_{i-2}dpi−1,dpi−2 才是已知的。

当前状态:
∣xys∣ \begin{vmatrix}x&y&s\end{vmatrix} xys

目标状态:
∣x+yxs+x+y∣ \begin{vmatrix}x+y&x&s+x+y\end{vmatrix} x+yxs+x+y

第一列:x+y=x×1+y×1+s×0x+y=x\times 1+y\times 1+s\times 0x+y=x×1+y×1+s×0

第二列:x=x×1+y×0+s×0x=x\times 1+y\times 0+s\times 0x=x×1+y×0+s×0

第三列:s+x+y=x×1+y×1+s×1s+x+y=x\times 1+y\times 1+s\times 1s+x+y=x×1+y×1+s×1

最终矩阵:
∣111101001∣ \begin{vmatrix}1&1&1\\1&0&1\\0&0&1\end{vmatrix} 110100111

推广 5

式子:
dpn=dpn−1+dpn−2+(n+1)2 dp_n=dp_{n-1}+dp_{n-2}+(n+1)^2 dpn=dpn−1+dpn−2+(n+1)2

对于 (n+1)2(n+1)^2(n+1)2,有 (n+1)2=n2+2n+1(n+1)^2=n^2+2n+1(n+1)2=n2+2n+1,所以我们需要维护 n2,nn^2,nn2,n 和 1。

当前状态:
∣xyn2n1∣ \begin{vmatrix}x&y&n^2&n&1\end{vmatrix} xyn2n1

目标状态:
∣x+y+n2+2n+1x(n+1)2n+11∣ \begin{vmatrix}x+y+n^2+2n+1&x&(n+1)^2&n+1&1\end{vmatrix} x+y+n2+2n+1x(n+1)2n+11

第一列:x+y+n2+2n+1=x×1+y×1+n2×1+n×2+1×1x+y+n^2+2n+1=x\times 1+y\times 1+n^2\times 1+n\times 2+1\times 1x+y+n2+2n+1=x×1+y×1+n2×1+n×2+1×1

第二列:x=x×1+y×0+n2×0+n×0+1×0x=x\times 1+y\times 0+n^2\times 0+n\times 0+1\times 0x=x×1+y×0+n2×0+n×0+1×0

第三列:(n+1)2=n2+2n+1=x×0+y×0+n2×1+n×2+1×1(n+1)^2=n^2+2n+1=x\times 0+y\times 0+n^2\times 1+n\times 2+1\times 1(n+1)2=n2+2n+1=x×0+y×0+n2×1+n×2+1×1

第四列:n+1=x×0+y×0+n2×0+n×1+1×1n+1=x\times 0+y\times 0+n^2\times 0+n\times 1+1\times 1n+1=x×0+y×0+n2×0+n×1+1×1

第五列:1=x×0+y×0+n2×0+n×0+1×11=x\times 0+y\times 0+n^2\times 0+n\times 0+1\times 11=x×0+y×0+n2×0+n×0+1×1

最终矩阵:
∣1100010000101002021010111∣ \begin{vmatrix}1&1&0&0&0\\1&0&0&0&0\\1&0&1&0&0\\2&0&2&1&0\\1&0&1&1&1\end{vmatrix} 1112110000001210001100001

总结

矩阵乘法优化递推时,我们用一个 1×N1\times N1×N 的矩阵表示需要用的状态,如 dpi,dpi−1,dpi−2⋯dp_i,dp_{i-1},dp_{i-2}\cdotsdpi,dpi−1,dpi−2⋯。

构造转移矩阵是比较难想,但是我们可以从最终的结果推,就像走迷宫从终点开始一样。

我们有一个 1×N1\times N1×N 的矩阵表示当前状态,还有一个 1×N1\times N1×N 的矩阵表示下一步的目标状态,有了这两个矩阵,就很容易推出中间 N×NN\times NN×N 的转移矩阵了。

相关推荐
kisshuan123962 小时前
【[特殊字符]深度矩阵】Intel DPT-SwinV2单目测距新突破
线性代数·矩阵
汉克老师14 天前
GESP2023年12月认证C++二级( 第三部分编程题(2) 小杨的H字矩阵)
c++·算法·矩阵·循环结构·gesp二级·gesp2级
AI科技星14 天前
物理世界的几何建构:论统一场论的本体论革命与概念生成
人工智能·opencv·线性代数·算法·矩阵
没有bug.的程序员14 天前
订单系统重构史诗:从单体巨兽到微服务矩阵的演进、数据一致性内核与分布式事务
java·微服务·矩阵·重构·分布式事务·数据一致性·订单系统
super_lzb14 天前
【线性代数】矩阵第一讲:矩阵与矩阵的运算
线性代数·矩阵·考研数学·矩阵的计算
newbiai14 天前
TikTok矩阵账号引流怎么解决效率低成本高?
python·线性代数·矩阵
逆境不可逃14 天前
【从零入门23种设计模式08】结构型之组合模式(含电商业务场景)
线性代数·算法·设计模式·职场和发展·矩阵·组合模式
菜鸡儿齐15 天前
leetcode-搜索二维矩阵
算法·leetcode·矩阵
炽烈小老头15 天前
【每天学习一点算法 2026/02/24】矩阵置零
学习·算法·矩阵