矩阵运算/矩阵快速幂
1.矩阵加减法
1.1矩阵加法
矩阵加法就是把两个矩阵对应的每一项相加,得出答案矩阵.显然,只有同型矩阵才能相加.
例:
1.2矩阵减法
矩阵减法就是把两个矩阵对应的每一项相减,得出答案矩阵.也显然,只有同型矩阵才能相减.
例:
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矩阵的数乘
一个数乘上一个矩阵,让这个数乘上矩阵的每一个数,得到答案矩阵,例如:
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}\).
显然可得:
(1)两矩阵做乘法运算时,只有当左边矩阵列数与右边矩阵的行数一致时才有意义.
(2)结果矩阵\(C\)的行数与\(A\)的行数相同,与\(B\)的列数相同.
例:
\(①\)用第一个矩阵的第\(1\)行乘上第二个矩阵的第\(1\)列,即对应元素相乘再相加,放在结果矩阵的第\(1\)行第\(1\)列;
\(②\)用第一个矩阵的第\(1\)行乘上第二个矩阵的第\(2\)列,即对应元素相乘再相加,放在结果矩阵的第\(1\)行第\(2\)列;
\(③\)用第一个矩阵的第\(1\)行乘上第二个矩阵的第\(3\)列,即对应元素相乘再相加,放在结果矩阵的第\(1\)行第\(3\)列;
\(④\)同理,依次用第一个矩阵的第\(2\)行乘上第二个矩阵的第\(1\)列、第\(2\)列和第\(3\)列,分别放在结果矩阵的第\(1\)列、第\(2\)列和第\(3\)列.
最终得到答案矩阵:
3.2矩阵乘法的运算律
3.2.1结合律
3.2.2分配律
3.2.3交换律
在矩阵乘法中,交换律不一定成立,例:
按照上面的计算方法分别可得:
显然\(AB\neq BA\).
当然从另一个方面也可证矩阵乘法的交换律不一定成立:
设\(A\)是一个\(m\times n\)的矩阵,\(B\)是一个\(r\times s\)的矩阵,那么\(AB\)是一个\(m\times s\)的矩阵,\(BA\)是一个\(r\times n\)的矩阵,也显然\(AB\neq BA\).
矩阵乘法的交换律不一定成立,那么下面的推论也不一定成立:
以上两种情况只有在\(AB=BA\)时,不等号变为等号.
3.3例题
洛谷B2105 矩阵乘法,讲课这么多,直接上代码.
#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次就是我们的矩阵快速幂了,或者说,矩阵快速幂就是把快速幂里的乘法换成矩阵乘法.
上代码
#include<bits/stdc++.h>//求矩阵A的k次方
using namespace std;
typedef long long ll;
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 k=1;k<=n;k++){
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
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 k=1;k<=n;k++){
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
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 jzksm(){
while(k){
if(k&1){
mul1();
}
mul2();
k>>=1;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>k;
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
cin>>a[i][j];
}
}
for(ll i=1;i<=n;i++){
ans[i][i]=1;
}
jzksm();
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
cout<<ans[i][j]<<" ";
}
cout<<"\n";
}
return 0;
}

浙公网安备 33010602011771号