本文轉自知乎,作者為王希(數學話題下的優秀回答者)
一句話先回答問題:因為斐波那契數列在數學和生活以及自然界中都非常有用。
下面我就盡我所能,講述一下斐波那契數列。
一、起源和定義
斐波那契數列最早被提出是印度數學家Gopala,他在研究箱子包裝物件長度恰好為1和2時的方法數時首先描述了這個數列。也就是這個問題:
而最早研究這個數列的當然就是斐波那契(Leonardo Fibonacci)了,他當時是為了描述如下情況的兔子生長數目:
第一個月初有一對剛誕生的兔子
第二個月之後(第三個月初)它們可以生育
每月每對可生育的兔子會誕生下一對新兔子
兔子永不死去
這個數列出自他赫赫有名的大作《計算之書》(沒有維基詞條,坑),後來就被廣泛的應用於各種場合了。這個數列是這麼定義的:
The On-Line Encyclopedia of Integer Sequences® (OEIS®)序號為A000045 - OEIS
(注意,並非滿足第三條的都是斐波那契數列,盧卡斯數列(A000032 - OEIS)也滿足這一特點,但初始項定義不同)
二、求解方法
講完了定義,再來說一說如何求對應的項。斐波那契數列是編程書中講遞歸必提的,因為它是按照遞歸定義的。所以我們就從遞歸開始講起。
1.遞歸求解
int Fib(int n)
{
return n < 2 ? 1 : (Fib(n-1) + Fib(n-2));
}
這是編程最方便的解法,當然,也是效率最低的解法,原因是會出現大量的重複計算。為了避免這種情況,可以採用遞推的方式。
2.遞推求解
int Fib[1000];
Fib[0] = 0;Fib[1] = 1;
for(int i = 2;i < 1000;i++) Fib[i] = Fib[i-1] + Fib[i-2];
遞推的方法可以在O(n)的時間內求出Fib(n)的值。但是這實際還是不夠好,因為當n很大時這個算法還是無能為力的。接下來就要來講一個有意思的東西:矩陣。
3.矩陣遞推關係
學過代數的人可以看出,下面這個式子是成立的:
不停地利用這個式子迭代右邊的列向量,會得到下面的式子:
這樣,問題就轉化為如何計算這個矩陣的n次方了,可以採用快速冪的方法。快速冪_百度百科是利用結合律快速計算冪次的方法。比如我要計算,我們知道,而可以通過來計算,而可以通過計算,以此類推。通過這種方法,可以在O(lbn)的時間裡計算出一個數的n次冪。快速冪的代碼如下:
int Qpow(int a,int n)
{
int ans = 1;
while(n)
{
if(n&1) ans *= a;
a *= a;
n >>= 1;
}
return ans;
}
將上述代碼中的整型變量a變成矩陣,數的乘法變成矩陣乘法,就是矩陣快速冪了。比如用矩陣快速冪計算斐波那契數列:
#include <cstdio>#include <iostream>
using namespace std;
const int MOD = 10000;
struct matrix//定義矩陣結構體
{
int m[2][2];
}ans, base;
matrix multi(matrix a, matrix b)//定義矩陣乘法
{
matrix tmp;
for(int i = 0; i < 2; ++i)
{
for(int j = 0; j < 2; ++j)
{
tmp.m[i][j] = 0;
for(int k = 0; k < 2; ++k)
tmp.m[i][j] = (tmp.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
}
}
return tmp;
}
int fast_mod(int n) // 求矩陣 base 的 n 次冪
{
base.m[0][0] = base.m[0][1] = base.m[1][0] = 1;
base.m[1][1] = 0;
ans.m[0][0] = ans.m[1][1] = 1; // ans 初始化為單位矩陣
ans.m[0][1] = ans.m[1][0] = 0;
while(n)
{
if(n & 1) //實現 ans *= t; 其中要先把 ans賦值給 tmp,然後用 ans = tmp * t
ans = multi(ans, base);
base = multi(base, base);
n >>= 1;
}
return ans.m[0][1];
}
int main()
{
int n;
while(scanf("%d", &n) && n != -1)
{
printf("%d\n", fast_mod(n));
}
return 0;
}
4.通項公式
無論如何,對於一個數列,我們都是希望可以建立與n的關係,也就是通項公式,而用不同方法去求解通項公式也是很有意思的。
(1)構造等比數列
設,
化簡得,
比較係數得,
解得,
由於
故有,設.則有
,設,
解得,即{}是等比數列。這樣就有
到了現在,把上述解出的結果全部帶入上式,稍作變形,我們就可以寫出斐波那契數列的通項公式了
這個方法還是比較麻煩的,但是非常基礎。事實上還有其他更簡單的方法。
(2)線性代數解法
這個解法首先用到
公式,如果可以找到矩陣使得為對角陣,我們就可以求出通項。下面需要一些高等代數知識,沒學過的可直接跳過。
首先令,解得兩個特徵根
兩個特徵向量為
則
而
解出,中間矩陣的n次方可以直接求出來:
然後可以輕易得到通項公式,上邊已經給出,這裡不再贅述。
(3)特徵方程解法
通過方法(2),我們可以推導出一般的線性遞推數列的通項求解方法,也就是特徵方程法。我們可以發現,對於這種數列,通項總是可以表示為的形式,因此可以直接利用已知項求解,。具體做法如下:
a.由遞推數列構造特徵方程,解出兩個特徵值。
b.帶入,列出如下方程:
解得這樣直接寫出通項公式,是比較簡單的做法。
(4)母函數法(此方法涉及組合數學知識)
設斐波那契數列的母函數為,即
解得
再由冪級數展開公式……
合併同類項並與的係數比較即可。
到這裡,求解斐波那契數列通項的方法就說的差不多了。無論是計算機求解還是數學推導,都體現出了非常多的技巧。而斐波那契數列的許多特性,就更加有意思了。
三、斐波那契數列的數學性質
1.與黃金比的關係
由通項公式,求相鄰兩項的商的極限,結果是黃金比,所以斐波那契數列又稱為黃金比數列。斐波那契數列和黃金比還和一個有趣的數學概念——連分數有關:
2.一些簡單的規律
(1)任意連續四個斐波那契數,可以構造出一個畢達哥拉斯三元組。如取1,1,2,3.
中間兩數相乘再乘2 ==》 4
外層2數乘積==》3
中間兩數平方和==》5
得到3,4,5.
下一組是5,12,13,,有興趣的讀者可以再試著推一推,證明也是容易的。
(2)整除性
每3個連續的斐波那契數有且只有一個被2整除,
每4個連續的斐波那契數有且只有一個被3整除,
每5個連續的斐波那契數有且只有一個被5整除,
每6個連續的斐波那契數有且只有一個被8整除,
每7個連續的斐波那契數有且只有一個被13整除,
…………
每n個連續的斐波那契數有且只有一個被整除.
(3)一些恆等式
3.楊輝三角中的斐波那契數列
如圖所示,每條斜線上的數的和就構成斐波那契數列。
即有
4.相關數列:盧卡斯(Lucas)數列
盧卡斯數列的定義除了第0項為2之外,與斐波那契數列完全一致。即
其通項公式為:
盧卡斯數列和斐波那契數列有這些關係:
5.組合數學
(1)一些恆等式
(2)同餘特性
當p為大於5的素數時,有:
其中
斐波那契數列還有許許多多的性質,我就不再一一介紹了。跑題了這麼久,終於開始要真正回答問題了:斐波那契數列有什麼用?
四、斐波那契數列的應用
1.算法
a.斐波那契堆
斐波那契堆(Fibonacci heap)是計算機科學中最小堆有序樹的集合。它和二項式堆有類似的性質,可用於實現合併優先隊列。特點是不涉及刪除元素的操作有O(1)的平攤時間,用途包括稠密圖每次Decrease-key只要O(1)的平攤時間,和二項堆的O(lgn)相比是巨大的改進。
斐波那契堆由一組最小堆構成,這些最小堆是有根的無序樹。可以進行插入、查找、合併和刪除等操作
1)插入:創建一個僅包含一個節點的新的斐波納契堆,然後執行堆合併
2)查找:由於用一個指針指向了具有最小值的根節點,因此查找最小的節點是平凡的操作。
3)合併:簡單合併兩個斐波納契堆的根表。即把兩個斐波納契堆的所有樹的根首尾銜接並置。
4)刪除(釋放)最小節點
分為三步:
查找最小的根節點並刪除它,其所有的子節點都加入堆的根表,即它的子樹都成為堆所包含的樹;
需要查找並維護堆的最小根節點,但這耗時較大。為此,同時完成堆的維護:對堆當前包含的樹的度數從低到高,迭代執行具有相同度數的樹的合併並實現最小樹化調整,使得堆包含的樹具有不同的度數。這一步使用一個數組,數組下標為根節點的度數,數組的值為指向該根節點指針。如果發現具有相同度數的其他根節點則合併兩棵樹並維護該數組的狀態。
對當前堆的所有根節點查找最小的根節點。
5)降低一個點的鍵值:對一個節點的鍵值降低後,自鍵值降低的節點開始自下而上的迭代執行下述操作,直至到根節點或一個未被標記(marked)節點為止:如果當前節點鍵值小於其父節點的鍵值,則把該節點及其子樹摘下來作為堆的新樹的根節點;其原父節點如果是被標記(marked)節點,則也被摘下來作為堆的新樹的根節點;如果其原父節點不是被標記(marked)節點且不是根節點,則其原父節點被加標記。
如果堆的新樹的根節點被標記(marked),則去除該標記。
6)刪除節點:把被刪除節點的鍵值調整為負無窮小,然後執行「降低一個節點的鍵值」算法,然後再執行「刪除最小節點」算法。
斐波那契堆
b.歐幾裡得算法的時間複雜度
歐幾裡得算法是求解兩個正整數最大公約數的算法,又稱輾轉相除法。代碼如下:
int gcd(int a,int b)
{
return b ? gcd(b,a%b) : a;
}
在最壞的情況下,我們可以證明,若a較小,需要計算的次數為n,則.雖然說一般分析的時候會當成對數階,但數論最常用的歐幾裡得算法竟然與斐波那契數列有關,也確實是很讓人吃驚呢。
2.物理學:氫原子能級問題
假定我們現在有一些氫氣原子,一個電子最初所處的位置是最低的能級(Ground lever of energy),屬於穩定狀態。它能獲得一個能量子或二個能量子(Quanta of energy)而使它上升到第一能級或者第二能級。但是在第一級的電子如失掉一個能量子就會下降到最低能級,它如獲得一個能量子就會上升到第二級來。
現在研究氣體吸收和放出能量的情形,假定最初電子是處在穩定狀態即零能級,然後讓它吸收能量,這電子可以跳到第1能級或第2能級。然後再讓這氣體放射能量,這時電子在1級能級的就要下降到0能級,而在第2能級的可能下降到0能級或者第1能級的位置去。
電子所處的狀態可能的情形是:1、2、3、5、8、13、21…種。這是斐波那契數列的一部份。
3.自然界:植物的生長
科學家發現,一些植物的花瓣、萼片、果實的數目以及排列的方式上,都有一個神奇的規律,它們都非常符合著名的斐波那契數列。例如:薊,它們的頭部幾乎呈球狀。在下圖中,你可以看到兩條不同方向的螺旋。我們可以數一下,順時針旋轉的(和左邊那條旋轉方向相同)螺旋一共有13條,而逆時針旋轉的則有21條。此外還有菊花、向日葵、松果、菠蘿等都是按這種方式生長的。
還有菠蘿、松子等,也都符合這個特點,一般會出現34,55,89和144這幾個數字。
最後上一張「斐波那契樹」的圖片:
是的,這玩意就長這樣,這種植物是存在的。
4.波浪理論與股市
這個答主不懂,大家可自行閱讀文章波浪理論斐波那契數列與黃金分割率。
不過波浪的形狀確實符合下邊要說的斐波那契螺旋:
5.斐波那契螺旋
斐波那契螺旋又稱黃金螺旋,在自然界中廣泛存在。如圖是一個邊長為斐波那契數列的正方形組成的矩形。
(加一句:看著這個圖,是不是能發現
是顯而易見的?)
這樣連起來就是斐波那契螺旋了
貝殼螺旋輪廓線
向日葵的生長
神奇的花
6.建築學
7.據說一個小男孩參考斐波那契數列發明了太陽能電池樹:
8.斐波那契螺旋形的搖椅
當Sophie宣布自己懷孕時,她說想要一把搖椅,但發現沒有一把搖椅能滿足美觀舒適的標準,於是Patrick決定自己做一把。
於是就有了這把媽媽搖椅。像是一個飄在空中的絲帶,由一片纖維玻璃做成,曲線服從斐波那契數列分布,經過特殊的高光聚氨酯處理。
五、數學上的擴展
(1)廣義斐波那契數列
定義:,數列滿足:
其通項為:
當時即為斐波那契數列。
(2)反斐波那契數列
定義:
反斐波那契數列相鄰項比值的極限為。
(3)巴都萬數列(A000931 - OEIS)
斐波那契數列可以刻畫矩形,而巴都萬數列則刻畫的是三角形。其定義如下:
(4)未解之謎:角谷猜想
對一個正整數,若為奇數則乘3加1,若為偶數則除以2,通過有限次這樣的操作,能否使得該數變成1?
這個猜想和斐波那契數列又很大關係,具體的可以看角谷猜想的斐波那契數列現象。
六、總結
斐波那契數列是各個學科中都出現的小滑頭,它許多漂亮的性質讓我們著迷。上文我所描述的這些只是它的冰山一角,權當拋磚引玉。大家讀完了我的答案,還可以再結合自己的專業去看一些相關的資料,更好的去了解這個有趣的數列。
七、參考文獻
[1]hytc.cn/xsjl/szh/lec5.p
[2]斐波那契數列_一米陽光
[3]斐波那契數列的規律性
[4]13歲男孩根據斐波那契數列發明太陽能電池樹_cnBeta 人物_cnBeta.COM
[5]服從斐波那契數列分布的媽媽搖椅
[6]從斐波那契數列到黃金分割
[7]斐波那契《計算之書》的研究.pdf 全文 文檔投稿網
[8]斐波那契數列
['9]費氏數列
[10]巴都萬數列
[11]zh.wikipedia.org/wiki/%
[12]角谷猜想的斐波那契數列現象
[13]The On-Line Encyclopedia of Integer Sequences® (OEIS®)
[14]波浪理論斐波那契數列與黃金分割率
【圖文來源】知乎
本文圖文來源於網絡,版權屬於原作者或網站,內容為作者觀點,並不代表本公眾號贊同其觀點及對其真實性負責。如有版權等問題,請與管理員郵箱聯繫,將立刻進行相應處理。