用矩陣表示數列遞推公式
羅維
2011年11月1日
中午隨便翻翻《編程之美》,讀了下求解Fibonacci數列這一章節。眾所周知,對於Fibonacci數列,其遞推關係式定義為:F(n) = F(n - 1) + F(n - 2), F(0) = 0, F(1) = 1。給定n,如何求出F(n)呢?
求解通項公式
學過組合數學的人應該會很自然的想到用特徵方程的方法來解出通項公式,其結果為
不過當用電腦在求解一個比較大的n下的F(n)值時,由於通項公式中引入了無理數,所以不能保證結果的精度。當然還是分析下這種方法的時空複雜度吧,這種演算法的空間複雜度為O(1),但是時間複雜度為O(log n)。書中認為時間複雜度是O(1),我認為是不對的,因為即使是調用庫函數來計算冪次方,庫函數在計算冪次方時,最快也只能達到O(log n)的複雜度。
矩陣方法解
由於Fabonacci數列是二階遞推數列,所以存在一個2*2的矩陣A,使得:
[Fn Fn-1] = [Fn-1 Fn-2] * A (1)
求解,其中A =
由(1)可以得到
[Fn Fn-1] = [Fn-1 Fn-1] * A = [Fn-2 Fn-3] * A2 = … = [F1 F0] * An-1
那如何求An呢?可以用分治策略來做,時間複雜度為O(log n),空間複雜度也是O(log n),具體的做法就參見《編程之美》中該專題的論述了。
用矩陣方法來表示數列遞推公式,就不會碰到無理數,能夠保證結果的精度;同時還能快速的得到針對某個M的餘數(這個根據同餘操作具有加法和乘法的性質可以論證)。
矩陣方法的發散
矩陣方法自然可以表示更多遞推公式,並給出對應的矩陣相乘的計算公式。例如:F(n) = F(n - 1) + F(n - 2) + F(n - 3),其中初始值F(0)、F(1)、F(2)的值可以為任意的整數;F(n) = 3F(n - 1) + 2F(n - 2),其中初始值可以為任意的整數。(當然初始值為小數,不會在計算An時引入一絲的計算誤差,而只是在最後一步的計算中影響結果的精度)
所以,形式化一點來講,對於遞推公式
F(n) = a1F(n - 1) + a2F(n - 2) + a3F(n - 3) + … + akF(n - k)
其中a1,a2,…,ak均為整數,初始值F(0), F(1), …, F(k - 1)可以為任意的初始值。對於這種形式的遞推公式,都可以考慮用矩陣來表示遞推公式。如下所示:
[Fn Fn-1 Fn-2 … Fn-k+1] = [Fn-1 Fn-2 Fn-3 … Fn-k] * A
= …
= [Fk-1 Fk-2 Fk-3 … F0] * An-k+1 (2)
其中A =
A為k*k方陣,同時第一列全為1,從第二列開始只有1個為1,其餘為0。
我們回過頭來看這個(2)式,
[Fn Fn-1 Fn-2 … Fn-k+1] = [Fk-1 Fk-2 Fk-3 … F0] * An-k+1
-------------------------- --------
第一部分 第二部分
簡要分析就可以看出:第一部分即為由初始值構成的1*k矩陣,第二部分即為融合了遞推公式資訊的k*k方陣。
總結矩陣表示數列遞推公式的好處:
- 用矩陣方法來表示數列遞推公式,就避免應用通項公式卻因為無理數而不能保證結果精度的麻煩。
- 同時還能快速地得到針對某個M的餘數。
前輩將矩陣這個工具引入到代數,是非常棒的貢獻!
(轉自http://luowei828.blog.163.com/blog/static/31031204201110133125750/)