Fibonacci数列

Fibonacci数列

Fibonacci数列是一个非常美丽、和谐的数列,有人说它起源于一对繁殖力惊人、基因非常优秀的兔子,也有人说远古时期的鹦鹉就知道这个规律。
每一个学理工科的学生都知道Fibonacci数列,Fibonacci数列由如下递推关系式定义:

F(0)=0, F(1)=1, n>1时,F(n)=F(n-1)+F(n-2)。

每一个上过算法课的同学都能用递归的方法求解Fibonacci数列的第n+1项的值,即F(n),以下为相关算法的代码:

int Fibonacci (int n)
{
    if (n <= 0) return 0;
    else if (n == 1) return 1;
    else return Fibonacci(n-1) + Fibonacci(n-2);
  }

那么问题来了,对于以上这种算法,能否进一步优化?

分析与解法

解法一:递推关系式的优化

上面列出的算法是根据递推关系式的定义直接得出的,它在计算F(n)时,需要计算从F(2)到F(n-1)每一项的值,这样简单的递归式存在着很多的重复计算,如F(5) = F(4) + F(3) , 在求F(4)的时候也需要计算一次F(3)的大小...等等。请问这个算法的时间复杂度是多少?
那么经过分析我们可以知道优化此类算法的重点在于减少重复计算。那么我们可以用一个数组存储所有已计算过的项。这样就可以达到用空间换取时间的目的。在这种情况下,时间复杂度为 O(N),而空间复杂度也为O(N)。
那么有更快的算法吗?

解法二:求解通项公式

如果我们知道一个数列的通项公式,使用公式来计算就会更加容易了。那么问题的关键就是能不能把这个函数的递推公式计算出来。
由递推公式: F(n)=F(n-1)+F(n-2),知道F(n)的特征方程为:
x² = x + 1 , 有两个特征根x1,x2。
则通项为F(n)= A x1 n + B x2 n( n次方,本人对markDown语法不是很熟练所以在此加以说明希望不要误导到读者,以上公式为:A倍 x1 的n次方) ,其中A,B可以通过F(0)和F(1)计算出来。

解法三:分治策略

因为Fibonacci数列是二阶递推数列,所以存在2*2的矩阵A,使得:

    [Fn Fn-1] = [Fn-1, Fn-2]*A
  通过递推可以求得A={{1, 1}{1, 0}}
  且:[Fn Fn-1] = [Fn-1, Fn-2]*A = [Fn-2, Fn-3]*A2= ... = [F1, F0]*An-1

剩下的问题就是求解矩阵A的方幂。
参考代码如下:

1 #include <iostream>
 2 using namespace std; 
 3 
 4 typedef long long LL; 
 5 const int maxn = 2; 
 6 const int MOD = 100000007; 
 7 
 8 struct Matrix 
 9 {
10     LL m[maxn][maxn]; 
11 }; 
12 
13 Matrix A = {1, 1, 1, 0}; 
14 Matrix I = {1, 0, 0, 1}; 
15 
16 Matrix multi(Matrix a, Matrix b)
17 {
18     Matrix c; 
19     for (int i = 0; i < maxn; i++)
20     {
21         for (int j = 0; j < maxn; j++)
22         {
23             c.m[i][j] = 0; 
24             for (int k = 0; k < maxn; k++)
25             {
26                 c.m[i][j] += a.m[i][k] * b.m[k][j] % MOD; 
27             }
28             c.m[i][j] %= MOD; 
29         }
30     }
31     return c; 
32 }
33 
34 Matrix power(Matrix A, int k)
35 {
36     Matrix ans = I, p = A; 
37     while (k)
38     {
39         if (k & 1)
40         {
41             ans = multi(ans, p); 
42             k--; 
43         }
44         k >>= 1; 
45         p = multi(p, p); 
46     }
47     return ans; 
48 }
49 
50 int main(int argc, char *argv[])
51 {
52     int n; 
53     while (cin >> n)
54     {
55         if (n <= 0) 
56         {
57             cout << 0 << endl;
58             continue; 
59         }
60         Matrix ans = power(A, n-1); 
61         cout << ans.m[0][0] << endl;
62     }
63 }

拓展

假设A(0)=1,A(1)=2,A(2)=2。对于n>2,都有A(k)=A(k-1)+A(k-2)+A(k-3)。```

(1) 对于任何一个给定的n,如何计算A(n)?

(2) 对于n非常大的情况,如n=260的时候,如何计算A(n)modM(M<100000)呢?```

 解答:

(1) [A(k) A(k-1) A(k-2)] = [A(k-1) A(k-2) A(k-3)]*B

其中B={{1, 1, 0}, {1, 0, 1}, {1, 0, 0}}。

(2)这个问题笔者思路如下,但并未通过代码证实:

A(n)modM取值为0,1,2,...,M-1,为有限的,因此,三元组[A(k) A(k-1) A(k-2)]共有M3种可能。

因此,A(n)modM是周期数列,而且,周期最大为M3。

可以先求出周期T,然后再求A[260]```

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容