矩陣快速冪和矩陣乘法


矩陣並不是一個數而是可以表示一個比較復雜的模型(集合),而集合里封裝着任意類型的值,而矩陣乘法則是一個比較重要的一個運算方式。

先說一下矩陣乘法的定義:

矩陣乘以矩陣的時候。

這個結果是怎么算出來的?

 

也就是說,結果矩陣第m行與第n列交叉位置的那個值,等於第一個矩陣第m行與第二個矩陣第n列,對應位置的每個值的乘積之和。

公式則是:其中cij為A的第i行與B的第j列對應乘積的和,即:

Cij =Σaik*bkj(1<=i<=n,1<=j<=n,1<=k<=n)。

Example(線性方程式)

矩陣的最初目的,只是為線性方程組提供一個簡寫形式。

附矩陣乘法的代碼

const int N=100;  
int c[N][N];  //c是最終的矩陣
void multi(int a[][N],int b[][N],int n)  
{  
    memset(c,0,sizeof c);  
    for(int i=1;i<=n;i++)  
        for(int j=1;j<=n;j++)  
          for(int k=1;k<=n;k++)  
            c[i][j]+=a[i][k]*b[k][j];  
} 

快速冪

求冪時我們常常會因結果太大而導致速度很慢,這時候我們就需要運用倍增的思想特殊的乘法應運而生————快速冪。

舉個例子,如果求a10,我們需要求十次,而如果我們用了快速冪就可以把a10轉變為二進制的形式從而加快運算速度。

而我們又知道ai=(ai/2)2

因此就有如下代碼

總的來說就是把指數變小,底數變大,讓運算次數變小的過程。(感覺我就這句話寫的有用

int fastpow(int a,int i)
{
    int ans=1;//ans是最后的結果
    int res=a;//res就相當於上文中的a的i-1次方。
    while (i>0)
    {
        if (i%2==1)//因為當I是奇數的時候你就不能再把它分成2進制啦
            ans=ans*res;//這時候就將res乘上去
        res=res*res;//底數不停變大
        i=i/2;指數縮小
    }
    return ans;
}

接下來就是矩陣快速冪了。

根據以上贅述,如果一個數能快速冪。那么一個矩陣也能快速冪。

原因:只要滿足結合律的數學運算就都可以使用快速冪

把快速冪與矩陣乘法相結合就是矩陣快速冪,其中快速冪的過程並不需要修改,只要定義一個關於矩陣的結構體並重載一下乘法運算符就可以了,為了方便運算,同時盡量滿足矩陣乘法的性質,下面的矩陣都是n*n的。

這就是矩陣乘法代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,k;
const long long MOD=1000000007;
struct Matrix
{
  long long m[100][100];
};
Matrix A,E,ANS;
Matrix cheng(Matrix X,Matrix Y)
{
  Matrix C;
  for(long long i=1; i<=n; i++)
    for(long long j=1; j<=n; j++)
      {
        C.m[i][j]=0;
        for(long long l=1; l<=n; l++)
          C.m[i][j]=(C.m[i][j]+(X.m[i][l]*Y.m[l][j]))%MOD;
      }
  return C;
}
Matrix qsort(Matrix X,long long p)
{
  Matrix S=E;
  while(p)
    {
      if(p&1) S=cheng(S,X);
      X=cheng(X,X);
      p>>=1;
    }
  return S;
}
int main()
{
  scanf("%lld%lld",&n,&k);
  for(long long i=1; i<=n; i++)
    E.m[i][i]=1;
  for(long long i=1; i<=n; i++)
    for(long long j=1; j<=n; j++)
      scanf("%lld",&A.m[i][j]);
  ANS=qsort(A,k);
  for(long long i=1; i<=n; i++)
    {
      for(long long j=1; j<=n; j++)
        printf("%lld ",ANS.m[i][j]);
      puts("");
    }
  return 0;
}

 

這個有什么用呢,我們下面再說。

矩陣優化

利用矩陣,我們可以優化許多有關於遞推和動態規划的問題。 我們先看一個簡單的例子:斐波那契數列 我們知道斐波那契數列的遞推式是

F[i]=F[i−1]+F[i−2]。

但是這樣遞推在i很大的時候效率不高,並且若不用滾動操作,空間消耗也很大。

所以我們可以轉變為:

求F(n)等於求二階矩陣的n - 1次方,結果取矩陣第一行第一列的元素。(因為要取矩陣的第一行才是Fn)。

問題轉換為二階矩陣的n次冪。

而計算二階矩陣的N次冪運算,由於矩陣乘法滿足結合律,這樣,可以快速計算二階矩陣的n次冪運算。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM