您的位置:首页 > 其它

斐波那契数的 O(lgn) 时间复杂度算法

2007-08-17 00:02 756 查看
看了算法导论的第 31 章的思考题 31-3,写了点代码。

This problem compares the efficiency of three methods for computing the nth Fibonacci number Fn, given n. Assume that the cost of adding, subtracting, or multiplying two numbers is O(1), independent of the size of the numbers.

Show that the running time of the straightforward recursive method for computing Fn based on recurrence (3.21) is exponential in n.

Show how to compute Fn in O(n) time using memoization.

Show how to compute Fn in O(lg n) time using only integer addition and multiplication. (Hint: Consider the matrix
0 1

1 1
and its powers.)

Assume now that adding two β-bit numbers takes Θ(β) time and that multiplying two β-bit numbers takes Θ(β2) time. What is the running time of these three methods under this more reasonable cost measure for the elementary arithmetic operations?

使用第三种算法,计算 矩阵
0 1
FibMat =
1 1
的 p 次幂(反复平方法),右下角的元素即为 Fp (假设数列从下标 0 开始)。


// 第 n 个 Fibinacci 数的 O(lgn) 时间复杂度的求法




#include <iostream>


using namespace std;




template <class T>


struct FibMat




{


T f00;


T f01;


T f10;


T f11;


FibMat (T a = 0, T b = 1, T c = 1, T d = 1);


void print ();


};




template <class T>


FibMat <T>::FibMat(T a, T b, T c, T d)




{


f00 = a;


f01 = b;


f10 = c;


f11 = d;


}




template <class T>


void FibMat <T>::print ()




{


cout << f00 << ' ' << f01 << endl;


cout << f10 << ' ' << f11 << endl;


}




template <class T>


FibMat <T> FibMat_Mul (FibMat <T> & a, FibMat <T> & b)




{


T f00 = a.f00 * b.f00 + a.f01 * b.f10;


T f01 = a.f00 * b.f01 + a.f01 * b.f11;


T f10 = a.f10 * b.f00 + a.f11 * b.f10;


T f11 = a.f10 * b.f01 + a.f11 * b.f11;


return FibMat <T> (f00, f01, f10, f11);


}




template <class T>


T FibCounter (int p)




{


FibMat <T> fm (0, 1, 1, 1); // 计算 fm 的 p 次幂,返回右下角的元素


FibMat <T> fm_pow (0, 1, 1, 1);


int j = 1;


while (j <= p)




...{


j <<= 1;


}


j >>= 1; // j 是不超过 p 的 2 幂


while (j >>= 1)




...{


fm_pow = FibMat_Mul (fm_pow, fm_pow);


if (j & p)




...{


fm_pow = FibMat_Mul (fm_pow, fm);


}


}


return fm_pow.f11;




}




int main ()




{


int i;


for (i = 1; i < 91; i ++)




...{


cout << FibCounter <long long> (i) << endl;


}


return 0;


}..................

运行结果:

1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
832040
1346269
2178309
3524578
5702887
9227465
14930352
24157817
39088169
63245986
102334155
165580141
267914296
433494437
701408733
1134903170
1836311903
2971215073
4807526976
7778742049
12586269025
20365011074
32951280099
53316291173
86267571272
139583862445
225851433717
365435296162
591286729879
956722026041
1548008755920
2504730781961
4052739537881
6557470319842
10610209857723
17167680177565
27777890035288
44945570212853
72723460248141
117669030460994
190392490709135
308061521170129
498454011879264
806515533049393
1304969544928657
2111485077978050
3416454622906707
5527939700884757
8944394323791464
14472334024676221
23416728348467685
37889062373143906
61305790721611591
99194853094755497
160500643816367088
259695496911122585
420196140727489673
679891637638612258
1100087778366101931
1779979416004714189
2880067194370816120
4660046610375530309

再接着算就超过 64 位有符号数的范围了。可以考虑用自定义的超长整数类来算。前几天我就花了 3 天时间来写了一个超长整数类,加减乘除的方法都写好了,速度不必 JAVA 的慢。HOHO~~有空会 post 出来开源o(∩_∩)o...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: