矩阵运算/矩阵快速幂

1.矩阵加减法

1.1矩阵加法

  矩阵加法就是把两个矩阵对应的每一项相加,得出答案矩阵。 显然,只有同型矩阵才能相加。

  例:

\\\begin{pmatrix} 1 \& 2 \\\\ 3 \& 4 \\\\ \\end{pmatrix} + \\begin{pmatrix} 2 \& 5 \\\\ 6 \& 1 \\\\ \\end{pmatrix} = \\begin{pmatrix} 3 \& 7 \\\\ 9 \& 5 \\\\ \\end{pmatrix} \\

1.2矩阵减法

  矩阵减法就是把两个矩阵对应的每一项相减,得出答案矩阵。也显然,只有同型矩阵才能相减。

  例:

\\\begin{pmatrix} 9 \& 6 \\\\ 8 \& 7 \\\\ \\end{pmatrix} - \\begin{pmatrix} 3 \& 5 \\\\ 4 \& 2 \\\\ \\end{pmatrix} = \\begin{pmatrix} 6 \& 1 \\\\ 4 \& 5 \\\\ \\end{pmatrix} \\

1.3矩阵加法单位元矩阵

  在某种运算下,任意元素与一个元素进行运算后还是其本身,那么这个元素就是单位元。例如加法的单位元是 \(0\),乘法的单位元是 \(1\)。

  设矩阵运算的单位元矩阵为 \(O\)。

1.4矩阵加法的运算律

  \(①A+B=B+A\)

  \(②(A+B)+C=A+(B+C\)

  \(③A+O=A\)

  \(④A+(-A)=O\)

  \(⑤A+B=C\Leftrightarrow A=C-B\)

2.矩阵的数乘

2.1矩阵的数乘

  一个数乘上一个矩阵,让这个数乘上矩阵的每一个数,得到答案矩阵,例如:

\5\\cdot \\begin{pmatrix} 1 \& 2 \\\\ 3 \& 4 \\\\ \\end{pmatrix} = \\begin{pmatrix} 5 \& 10 \\\\ 15 \& 20 \\\\ \\end{pmatrix} \\

2.2矩阵数乘的运算律

  \(①k(A+B)=kA+kB\)

  \(②(p+q)A=pA+qA\)

  \(③pq(A)=(pq)A\)

3.矩阵的乘法

3.1矩阵乘法运算法则

  设两个矩阵 \(A_{n,m}\)、\(B_{m,p}\),则它们相乘得到矩阵 \(C_{n,p}\)。

\C_{i,j}=\\sum_{1\\leq k\\leq m}A_{i,k}\\ast B_{k,j} \\

  显然可得:

  (1)两矩阵做乘法运算时,只有当左边矩阵列数与右边矩阵的行数一致时才有意义。

  (2)结果矩阵 \(C\) 的行数与 \(A\) 的行数相同,与 \(B\) 的列数相同。

  例:

\\\begin{pmatrix} 2 \& 1 \& 0 \\\\ 1 \& 0 \& 1 \\\\ \\end{pmatrix} \\cdot \\begin{pmatrix} 1 \& 0 \& 1 \\\\ 0 \& 1 \& 1 \\\\ 0 \& 1 \& 1 \\\\ \\end{pmatrix} \\

  \(①\) 用第一个矩阵的第 \(1\) 行乘上第二个矩阵的第 \(1\) 列,即对应元素相乘再相加,放在结果矩阵的第 \(1\) 行第 \(1\) 列;

\\\begin{pmatrix} \\color{red}{2} \& \\color{red}{1} \& \\color{red}{0} \\\\ 1 \& 0 \& 1 \\\\ \\end{pmatrix} \\cdot \\begin{pmatrix} \\color{red}{1} \& 0 \& 1 \\\\ \\color{red}{0} \& 1 \& 1 \\\\ \\color{red}{0} \& 1 \& 1 \\\\ \\end{pmatrix} = \\begin{pmatrix} \\color{red}{2\\times1+1\\times0+0\\times0} \& \\cdots \\\\ \\vdots \& \\ddots \\\\ \\end{pmatrix} \\

  \(②\) 用第一个矩阵的第 \(1\) 行乘上第二个矩阵的第 \(2\) 列,即对应元素相乘再相加,放在结果矩阵的第 \(1\) 行第 \(2\) 列;

\\\begin{pmatrix} \\color{red}{2} \& \\color{red}{1} \& \\color{red}{0} \\\\ 1 \& 0 \& 1 \\\\ \\end{pmatrix} \\cdot \\begin{pmatrix} 1 \& \\color{red}{0} \& 1 \\\\ 0 \& \\color{red}{1} \& 1 \\\\ 0 \& \\color{red}{1} \& 1 \\\\ \\end{pmatrix} = \\begin{pmatrix} 2 \& \\color{red}{2\\times0+1\\times1+0\\times1} \& \\cdots \\\\ \\vdots \& \\vdots \& \\ddots \\\\ \\end{pmatrix} \\

  \(③\) 用第一个矩阵的第 \(1\) 行乘上第二个矩阵的第 \(3\) 列,即对应元素相乘再相加,放在结果矩阵的第 \(1\) 行第 \(3\) 列;

\\\begin{pmatrix} \\color{red}{2} \& \\color{red}{1} \& \\color{red}{0} \\\\ 1 \& 0 \& 1 \\\\ \\end{pmatrix} \\cdot \\begin{pmatrix} 1 \& 0 \& \\color{red}{1} \\\\ 0 \& 1 \& \\color{red}{1} \\\\ 0 \& 1 \& \\color{red}{1} \\\\ \\end{pmatrix} = \\begin{pmatrix} 2 \& 1 \& \\color{red}{2\\times0+1\\times1+0\\times1} \\\\ \\vdots \& \\vdots \& \\ddots \\\\ \\end{pmatrix} \\

  \(④\) 同理,依次用第一个矩阵的第 \(2\) 行乘上第二个矩阵的第 \(1\) 列、第 \(2\) 列和第 \(3\) 列,分别放在结果矩阵的第 \(1\) 列、第 \(2\) 列和第 \(3\) 列。

\\\begin{pmatrix} 2 \& 1 \& 0 \\\\ \\color{red}{1} \& \\color{red}{0} \& \\color{red}{1} \\\\ \\end{pmatrix} \\cdot \\begin{pmatrix} \\color{red}{1} \& \\color{red}{0} \& \\color{red}{1} \\\\ \\color{red}{0} \& \\color{red}{1} \& \\color{red}{1} \\\\ \\color{red}{0} \& \\color{red}{1} \& \\color{red}{1} \\\\ \\end{pmatrix} = \\begin{pmatrix} 2 \& 1 \& 3 \\\\ \\color{red}{1} \& \\color{red}{1} \& \\color{red}{2} \\\\ \\end{pmatrix} \\

  最终得到答案矩阵:

\\\begin{pmatrix} 2 \& 1 \& 3 \\\\ 1 \& 1 \& 2 \\\\ \\end{pmatrix} \\

3.2矩阵乘法的运算律

3.2.1结合律

\(AB)C=A(BC) \\

3.2.2分配律

\A(B+C)=AB+AC\\\\ (B+C)A=BA+BC \\

3.2.3交换律

  在矩阵乘法中,交换律不一定成立,例:

\A= \\begin{pmatrix} 2 \& 1 \\\\ 1 \& -1 \\\\ \\end{pmatrix}\\space B= \\begin{pmatrix} 0 \& 1 \\\\ -1 \& 2 \\\\ \\end{pmatrix}\\\\ \\

  按照上面的计算方法分别可得:

\AB= \\begin{pmatrix} -1 \& 4 \\\\ 1 \& -1 \\\\ \\end{pmatrix} \\

\AB= \\begin{pmatrix} 1 \& -1 \\\\ 0 \& -3 \\\\ \\end{pmatrix} \\

  显然 \(AB\neq BA\)。

  当然从另一个方面也可证矩阵乘法的交换律不一定成立:

  设 \(A\) 是一个 \(m\times n\) 的矩阵,\(B\) 是一个 \(r\times s\) 的矩阵,那么 \(AB\) 是一个 \(m\times s\) 的矩阵,\(BA\) 是一个 \(r\times n\) 的矩阵,也显然 \(AB\neq BA\)。

  矩阵乘法的交换律不一定成立,那么下面的推论也不一定成立:

\(A+B)\^2=(A+B)(A+B)=A\^2+AB+BA+B\^2\\neq A\^2+2AB+B\^2 \\

\(A+B)(A-B)=A\^2-AB+BA-B\^2\\neq A\^2-B\^2 \\

  以上两种情况只有在 \(AB=BA\) 时,不等号变为等号。

3.3例题

  洛谷B2105 矩阵乘法,讲了这么多,直接上代码。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,k,a[105][105],b[105][105],ans[105][105];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>n>>m>>k;
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	for(ll i=1;i<=m;i++){
		for(ll j=1;j<=k;j++){
			cin>>b[i][j];
		}
	}
	for(ll p=1;p<=m;p++){
		for(ll i=1;i<=n;i++){
			for(ll j=1;j<=k;j++){
				ans[i][j]+=a[i][p]*b[p][j];
			}
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=k;j++){
			cout<<ans[i][j]<<" ";
		}
		cout<<"\n";
	}
	return 0;
}

4.矩阵快速幂

  快速幂不会的看这里:快速幂模版,会了矩阵运算,会了快速幂,那么矩阵乘法 \(+\) 快速幂 \(=\) 矩阵快速幂。

  因为矩阵乘法是满足结合律的,所以一个单位矩阵用快速幂乘上 \(n\) 次就是我们的矩阵快速幂了,或者说,矩阵快速幂就是把快速幂里的乘法换成矩阵乘法。

  洛谷P3390 【模板】矩阵快速幂

  上代码

cpp 复制代码
#include<bits/stdc++.h>//求矩阵A的k次方
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e2+5,mod=1e9+7;
ll n,k,a[maxn][maxn],c[maxn][maxn],ans[maxn][maxn];
void mul1(){
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			c[i][j]=0;
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			for(ll k=1;k<=n;k++){
				c[i][j]=(c[i][j]+ans[i][k]*a[k][j])%mod;
			}
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			ans[i][j]=c[i][j];
		}
	}
}
void mul2(){
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			c[i][j]=0;
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			for(ll k=1;k<=n;k++){
				c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
			}
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			a[i][j]=c[i][j];
		}
	}
}
void ksm(ll b){//快速幂模版
	while(b){
		if(b&1){
			mul1();//把这里改成矩阵的乘法
		}
		mul2();//这里也是,注意这两次相乘的矩阵不一样
		b>>=1;
	}
}
int main(){
	n=rd();
	k=rd();
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			a[i][j]=rd();
		}
		ans[i][i]=1;
	}
	ksm(k);
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			write(ans[i][j]);
			putchar(' ');
		}
		putchar('\n');
	}
	return 0;
}