矩陣性質 矩陣加速遞推

2022-09-10 21:42:21 字數 3341 閱讀 7591

本文介紹線性代數中乙個非常重要的內容——矩陣(matrix)的乙個重要性質:矩陣加速遞推同時本文已經更新至:矩陣(matrix)系統介紹篇

斐波那契數列(fibonacci sequence)大家應該都非常的熟悉了。在斐波那契數列當中,\(f_1 = f_2 = 1\),\(f_i = f_ + f_(i \geq 3)\)。

如果有一道題目讓你求斐波那契數列第 \(n\) 項的值,最簡單的方法莫過於直接遞推了。但是如果 \(n\) 的範圍達到了 \(10^\) 級別,遞推就不行了,穩 tle。考慮矩陣加速遞推。

設 \(fib(n)\) 表示乙個 \(1 \times 2\) 的矩陣 \(\left[ \beginf_n & f_ \end\right]\)。我們希望根據 \(fib(n-1)=\left[ \beginf_ & f_ \end\right]\) 推出 \(fib(n)\)。

試推導乙個矩陣 \(\text\),使 \(fib(n-1) \times \text = fib(n)\),即 \(\left[\beginf_ & f_\end\right] \times \text = \left[ \beginf_n & f_ \end\right]\)。

怎麼推呢?因為 \(f_n=f_+f_\),所以 \(\text\) 矩陣第一列應該是 \(\left[\begin 1 \\ 1 \end\right]\),這樣在進行矩陣乘法運算的時候才能令 \(f_\) 與 \(f_\) 相加,從而得出 \(f_n\)。同理,為了得出 \(f_\),矩陣 \(\text\) 的第二列應該為 \(\left[\begin 1 \\ 0 \end\right]\)。

綜上所述:\(\text = \left[\begin 1 & 1 \\ 1 & 0 \end\right]\) 原式化為 \(\left[\beginf_ & f_\end\right] \times \left[\begin 1 & 1 \\ 1 & 0 \end\right] = \left[ \beginf_n & f_ \end\right]\)

轉化為**,應該怎麼求呢?

定義初始矩陣 \(\text = \left[\beginf_2 & f_1\end\right] = \left[\begin1 & 1\end\right], \text = \left[\begin 1 & 1 \\ 1 & 0 \end\right]\)。那麼,\(f_n\) 就等於 \(\text \times \text^\) 這個矩陣的第一行第一列元素,也就是 \(\left[\begin1 & 1\end\right] \times \left[\begin 1 & 1 \\ 1 & 0 \end\right]^\) 的第一行第一列元素。

注意,矩陣乘法不滿**換律,所以一定不能寫成 \(\left[\begin 1 & 1 \\ 1 & 0 \end\right]^ \times \left[\begin1 & 1\end\right]\) 的第一行第一列元素。另外,對於 \(n \leq 2\) 的情況,直接輸出 \(1\) 即可,不需要執行矩陣快速冪。

為什麼要乘上 \(\text\) 矩陣的 \(n-2\) 次方而不是 \(n\) 次方呢?因為 \(f_1, f_2\) 是不需要進行矩陣乘法就能求的。也就是說,如果只進行一次乘法,就已經求出 \(f_3\) 了。如果還不是很理解為什麼冪是 \(n-2\),建議手算一下。

下面是求斐波那契數列第 \(n\) 項對 \(10^9+7\) 取模的示例**(核心部分)。

const int mod = 1000000007;

struct matrix

matrix operator*(const matrix &b) const

} ans, base;

void init()

void qpow(int b)

}int main()

這是乙個稍微複雜一些的例子。

\[f_ = f_ = 0\\

f_ = 7f_+6f_+5n+4\times 3^n

\]我們發現,\(f_n\) 和 \(f_, f_, n\) 有關,於是考慮構造乙個矩陣描述狀態。

但是發現如果矩陣僅有這三個元素 \(\beginf_n& f_& n\end\) 是難以構造出轉移方程的,因為乘方運算和 \(+1\) 無法用矩陣描述。

於是考慮構造乙個更大的矩陣。

\[\beginf_n& f_& n& 3^n & 1\end

\]我們希望構造乙個遞推矩陣可以轉移到

\[\begin

f_& f_& n+1& 3^ & 1

\end

\]轉移矩陣即為

\[\begin

7 & 1 & 0 & 0 & 0\\

6 & 0 & 0 & 0 & 0\\

5 & 0 & 1 & 0 & 0\\

12 & 0 & 0 & 3 & 0\\

5 & 0 & 1 & 0 & 1

\end

\]有了上面的基礎能很快做出 又見斐波那契

圖源來自網路上一位博主

這個相比普通的斐波那契數列多了後面四項,看一眼資料範圍,使用普通的 \(o(n)\) 的演算法肯定會超時

因此這裡需要使用矩陣快速冪(斐波那契數列的項數n一旦過大,就要考慮快速冪,普通演算法時間空間都開銷太大)。

使用矩陣快速冪的乙個關鍵問題就是矩陣遞推式。

然後通過計算等價替換可得出該矩陣a:

下面只需要把普通斐波那契數列的構造由2*2的矩陣換為6*6的即可。

using ll = long long;

const int mod = 1e9 + 7;

const int n = 6;

ll tmp[n][n], res[n][n];

ll n;

void mul(ll a[n], ll b[n])

for (int i = 0; i < n; ++i)

for (int j = 0; j < n; ++j)a[i][j] = tmp[i][j];

}void pow(ll a[n])

}void solve() ;

pow(ans);

ll sum = 0;

ll x[n] = ;

for (int i = 0; i < n; ++i)

cout << sum << "\n";

}

矩陣加速遞推

關於矩陣加速數列遞推 給定乙個遞推數列 f i a 1 f i 1 a 2 f i 2 a k f i k 我們普通計算的話肯定是逐個計算,複雜度較大。我們可以用矩陣表示 left begin f i f i 1 f i k end right 為了遞推出 f n 我們需要找到乙個係數矩陣 a 使得...

模板 矩陣加速(數列)(矩陣加速遞推)

a 1 a 2 a 3 1 a x a x 3 a x 1 x 3 求a數列的第n項對1000000007 10 9 7 取餘的值。輸入格式 第一行乙個整數t,表示詢問個數。以下t行,每行乙個正整數n。輸出格式 每行輸出乙個非負整數表示答案。矩陣加速裸題 和我的前一篇基本一模一樣 只不過改變了要乘的...

矩陣加速遞推 入門指南

首先是乙個例題,輸入n和m,問用1x2的方塊填滿4xn的格仔共有多少種方案數,答案對m取模。分析問題可以找出所有狀態,用乙個1x4的位表示一行的方塊情況,0表示暫時為空,1表示恰好填入方塊。雖然4個二進位制位共有16中可能,但是合法的方案數實際只有6中,0000 0011 0110 1001 110...