矩陣運算
矩陣加、減法
矩陣加法非常簡單,對應位置直接加減即可,但是前提是兩個矩陣大小相同(即一個矩陣是N*M的,另一個與之相加的矩陣的大小也要是N*M)。就像這樣:
矩陣乘法
矩陣乘法就相對比較復雜了。他需要滿足的前提是第一個矩陣的列數要等於第二個矩陣的行數,這樣的兩個矩陣才可以相乘。下面我用一個圖來解釋怎麽樣進行矩陣乘法:
矩陣乘法性質:
①矩陣乘法滿足乘法結合律————A*B*C=(A*B)*C=A*(B*C)
②矩陣乘法滿足左分配律和右分配律————C*(A+B)=C*A+C*B || (A+B)*C=A*C+B*C
③矩陣乘法不滿足交換律————A*B!=B*A
下面是矩陣乘法的代碼:
#include<bits/stdc++.h>
using namespace std;
int m1[10][10],m2[10][10],m3[10][10]; //m1*m2=m3
int main(){
register int a,b,c;
//矩陣m1大小為n*m 矩陣m2大小為m*k 矩陣m3大小為n*k
for(a=1;a<=n;++a)
for(b=1;b<=m;++b)
for(c=1;c<=k;++c)
m3[a][c]+=m1[a][b]*m2[b][c];
return 0;
}
應用:矩陣乘法可以用來求斐波那契數列的第n項
用矩陣乘法求斐波那契數列的第n項,如果n比較的大的話就需要用到矩陣KSM了,不會的可以看一下這篇博客:https://www.cnblogs.com/Glacier-elk/p/9489655.html
洛谷原題鏈接:https://www.luogu.org/problemnew/show/P1962
在這道題目中保證n在long long的範圍內,這就需要用到矩陣乘法和矩陣快速冪了。首先我們要知道怎麽樣用矩陣求斐波那契數列,也就是確定矩陣A和矩陣B分別是什麽。其中一個矩陣肯定是存放斐波那契數列的,我們不妨就讓矩陣A是斐波那契數列,讓矩陣A是一個1*2的矩陣,分別存放第n項和第n-1項,則矩陣A可以表示為
。那矩陣B就需要使A*B可以得到斐波那契的下一項。首先我們可以確定的是,矩陣B是一個2*2的矩陣,因為矩陣乘法需要滿足一個矩陣的列數等於另一個矩陣的行數。所以我們不妨設矩陣B為,那麽這樣的話C就可以表示為,因為C也可以表示為,我們就可以用斐波那契數列的前幾項列出幾個方程組,就可以求出矩陣B的元素了。通過計算,我們發現矩陣B為。我們還可以發現,矩陣A每乘一次矩陣B,數列就可以向前遞進一項,所以我們求第n項,就需要用矩陣A乘n-2遍矩陣B,也就是矩陣A乘矩陣B的n-2次方,這樣我們就可以用矩陣快速冪求解。
下面是AC代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll n,b[3][3],a[2][2],ans[3][3]={0,0,0,0,1,1,0,1,1},c[3][3];
void mul(int x){
register int i,j,k;
memset(c,0,sizeof(c));
for(i=1;i<=2;++i)
for(j=1;j<=2;++j)
for(k=1;k<=2;++k)
if(x) c[i][k]+=ans[i][j]*b[j][k],c[i][k]%=mod;
else c[i][k]+=b[i][j]*b[j][k],c[i][k]%=mod;
for(i=1;i<=2;++i)
for(j=1;j<=2;++j)
if(x) ans[i][j]=c[i][j];
else b[i][j]=c[i][j];
}
void ksm(ll cur){
while(cur){
if(cur & 1) mul(1);
cur>>=1;
mul(0);
}
printf("%lld",ans[1][1]%mod);
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
if(n<=2){
cout<<"1";
return 0;
}
ans[1][1]=1,ans[1][2]=1,b[1][1]=1,b[1][2]=1,b[2][1]=1,b[2][2]=0;
ksm(n-2);
return 0;
}
矩陣運算