现在的位置: 首页 > 综合 > 正文

19 用最快的方法求该数列的第 n 项

2018年01月19日 ⁄ 综合 ⁄ 共 1265字 ⁄ 字号 评论关闭
<pre name="code" class="cpp">/*
第 19  题: 
题目:定义 Fibonacci  数列如下:
f(n)=1 n=0
f(n)= 1 n=1
f(n-1)+f(n-2) n=2
输入n,用最快的方法求该数列的第 n 项。

基本的方法有2种

还有个网上方法: 
其数学基础:
方阵{ f(n), f(n-1), f(n-1), f(n-2) } = {1, 1, 1,0 }n-1方 
即前者表示一个2X2的方阵,
后者表示一个第一行为1,1、第二行为1,0的方阵的n-1次方。
矩阵{1,1,1,0}的n-1次方的结果的第一行第一列就是f(n),


现在的问题转换为求矩阵{1, 1, 1, 0}的乘方。

但我们可以考虑乘方的如下性质:
        /   an/2*an/2                      n为偶数时 
an= 
        \  a(n-1)/2*a(n-1)/2              n为奇数时
要求得n次方,我们先求得n/2次方,再把n/2的结果平方一下。

分治法。求n变为2个n/2 
这样求n次方就只需要logn次运算了。
*/

#include <iostream>  
using namespace std;  
   
// 递归方法,时间复杂度O(n)  
int Fibonacci1(int n)  
{  
    if (n==0||n==1)  
        return n;  
    else  
        return Fibonacci1(n-1)+Fibonacci1(n-2);  
}  
   
// 额外空间循环方法,时间复杂度O(n)  
int Fibonacci2(int n)  
{  
    int result=0;  
    int f1=0,f2=1;
	 
    if (n==0||n==1)  
        return n;  
    else  
    {  
        for (int i=1;i<n;i++)  
        {  
            result=f1+f2;  
            f1=f2;  
            f2=result;  
        }  
    }  
    return result;  
}  


void multiply(int A[], int B[], int result[])  
{ 
     result[0] = A[0]*B[0] + A[1]*B[2]; 
     result[1] = A[0]*B[1] + A[1]*B[3]; 
     result[2] = A[2]*B[0] + A[3]*B[2]; 
     result[3] = A[2]*B[1] + A[3]*B[3]; 
} 

void power(int A[], int n, int result[])  
 { 
    if (n==1)  
     {  
        memcpy(A,result,4*sizeof(int));  
        return;  
     } 
     int tmp[4]; 
     power(A, n>>1,result); 
     multiply(result,result,tmp); 
  
     if (n&1==1)  
     { 
          multiply(tmp, A, result); 
     }  
     else  
     { 
        memcpy(result,tmp,4*sizeof(int)); 
     } 
} 
 int Fibonacci3(int n)  
 { 
     int A[4] = {1,1,1,0}; 
     int result[4]={1,1,1,0}; 
     power(A, n, result); 
     return result[0];
 } 
 
int main()  
{  
    cout<<Fibonacci2(10)<<endl;  
    cout<<Fibonacci1(10)<<endl;  
    cout<<Fibonacci3(10-1)<<endl;  
    return 0;  
} 

抱歉!评论已关闭.