1. 程式人生 > >矩陣運算

矩陣運算

pac div 得到 加法 main register 題目 tex 相同

矩陣加、減法

矩陣加法非常簡單,對應位置直接加減即可,但是前提是兩個矩陣大小相同(即一個矩陣是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;
}

矩陣運算