矩陣相關(研究總結,矩陣,矩陣快速冪)
矩陣是計算機數學里一個比較重要的內容,它可以優化很多地方的推導,這里簡要地總結一下
什么是矩陣
形如
或
通用形式
這就是矩陣
簡單點來說,就是一個二維數組
矩陣乘法
說完了矩陣,那么什么是矩陣乘法呢?
首先說明一點,矩陣乘法A*B要求滿足A的行數等於B的列數!,這是由矩陣乘法的運算性質來的。
我們設A*B=T(三個都是矩陣),那么對於T[i][j]來說,$$T[i][j]=\Sigma(A[i][k]*B[k][j])$$
舉個例子
(寫得有點長,仔細閱讀后可以找到規律)
用字母表示就是
說的通俗一點,結果矩陣的第i行第j列等於矩陣A第i行與矩陣B第j列分別乘積的和(現在明白為什么矩陣乘法要求A的行數與B的列數相同了吧,因為要保證有東西乘,若不相等會導致缺少一些項)
快速冪
如果要求數字X的k次方,我們該如何求呢?
最簡單的方法就是用一個循環,循環k次,每次相乘。
但這樣效率太低,下面來介紹一下快速冪的方法。
我們知道,任何一個十進制的數都可以表示成為二進制的形式,比如12轉成二進制就是1100,這同樣也表示$$12=2^3+2^2$$
那么對於任意一個數k,它就可以表示為:
而我們又知道:
這就可以加速我們的冪運算,下面先給出代碼:
int pow(int x,int k)
{
int ans=1;
int res=x;
while (k>0)
{
if (k%2==1)
ans=ans*res;
res=res*res;
k=k/2;
}
return ans;
}
解釋一下,ans就是最后我們返回的x^k的值,而res則是一個累乘器,它基於的原理就是上面給出的
當然,上面這個代碼還不是最快的,還可以用位運算優化一下
int pow(int x,int k)
{
int ans=1;
int res=x;
while (k>0)
{
if (k&1)
ans=ans*res;
res=res*res;
k=k>>1;
}
return ans;
}
快速冪與矩陣
把快速冪與矩陣乘法相結合就是矩陣快速冪,其中快速冪的過程並不需要修改,只要定義一個關於矩陣的結構體並重載一下乘法運算符就可以了,為了方便運算,同時盡量滿足矩陣乘法的性質,下面的矩陣都是n*n的。
class Matrix
{
public:
int n;//n是當前矩陣的大小
int A[maxN][maxN];//maxN就是矩陣的最大大小
Matrix()//初始化矩陣中的所有元素都為0
{
memset(A,0,sizeof(A));
}
}
Matrix operator * (Matrix A,Matrix B)//重載乘法運算
{
Matrix Ans;
int size=A.n;
Ans.n=size;
for (int i=0;i<size;i++)
for (int j=0;j<size;j++)
for (int k=0;k<size;k++)
Ans.A[i][j]+=A.A[i][k]*B.A[k][j];
return Ans;
}
這個有什么用呢,我們下面再說。
矩陣優化
利用矩陣,我們可以優化許多有關於遞推和動態規划的問題。
我們先看一個簡單的例子:斐波那契數列
我們知道斐波那契數列的遞推式是
但是這樣遞推在i很大的時候效率不高,並且若不用滾動操作,空間消耗也很大。
(你說用通項公式?抱歉,無理數的精度是個問題)
我們考慮如何用矩陣來優化。
什么意思,就是我們希望得到一個式子滿足F[i]=A*A[i-1],這樣我們就可以直接得到直接求出F[n]的式子,
再結合快速冪,我們就可以快速解決了。
先別急,我們先想一想我們需要那些狀態。
要求出f[i](注意,這里我們開始用小寫,因為我們用大寫表示矩陣,而用小寫表示原來的遞推式中的元素),我們至少需要知道f[i-1]和f[i-2]的信息,所以我們可以列出下面這樣的信息矩陣:
我們再看一看我們要得到怎樣的目標狀態呢?
直接看f[i+1]需要那些元素,很明顯,f[i+1]由f[i]和f[i-1]推來,所以我們可以列出下面的目標矩陣:
根據斐波那契數列的普通遞推式,我們又可以把上面這個矩陣表示成為下面這種形式:
現在的任務就是要找出一個一個矩陣T使得F[i-1]*T=F[i]
根據矩陣乘法的運算法則,我們可以得出這個矩陣T:
(這里推薦讀者手動計推算一下)
當然,為了方便運算,這里我們把矩陣都補成正方形,方便存儲和運算
有了轉移矩陣T,我們就可以用快速冪迅速求出斐波那契數列的任意一項了。
好題推薦
下面給出一些矩陣乘法優化的題目,它們都是一些遞推的題目,但加強了數據范圍,讀者可以去熟悉矩陣的相關計算
Luogu 3390 【模板】矩陣快速冪 (矩陣乘法,快速冪)(一道矩陣快速冪模板題)
Luogu 1962 斐波那契數列(矩陣,遞推)(就是文章中那個斐波那契數列的例子)
Luogu 1349 廣義斐波那契數列(遞推,矩陣,快速冪)(斐波那契數列的加強版,不再是簡單的f[i]=f[i-1]+f[i-2],而是f[i]=a*f[i-1]+b*f[i-2],並且初始值f[1]和f[2]也是給定的)
Luogu T7152 細胞(遞推,矩陣乘法,快速冪)(稍微復雜點的用矩陣優化的遞推)
CJOJ 1331 【HNOI2011】數學作業 / Luogu 3216 【HNOI2011】數學作業 / HYSBZ 2326 數學作業(遞推,矩陣)(HNOI往年省選題,需要特殊處理的矩陣快速冪)
更多題目可以到右側我的隨筆分類中數學---矩陣中查看