以最快的速度求出Fibonacci 序列的第n项

题目:定义Fibonacci序列如下:f(0)=0,f(1)=f(2)=1,n>2时,f(n)=f(n-1)+f(n-2) ,输入n ,用最快的方法求该数列的第 n 项。

分析:

首先递归求法肯定都会,但是由于递推关系的形式,很容易看出里面有很多的重复计算。改进的方法也很容易想到,即申请额外的两个空间来存放保存前面的计算结果,以此来提供速度:

参考代码:

1: int getNthFibonacci(int n) 
2: {  
3:     int first=0,second=1;  
4:     if(n==0 || n==1)  
5:         return n;   
6: 
7:     int result=0;   
8:     for(int i=1;i<n;i++)  
9:     {  
10:         result += first+second;
11:         first=second;  
12:         second=result;  
13:     } 
14:     return result;  
15: }

这里时间复杂度为O(n),网上还有一种时间复杂度为log(n)的算法,思想如下:

其数学基础:方阵{ 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}的乘方。如果简单第从0开始循环,n次方将需要n次运算,并不比前面的方法要快。但我们可以考虑乘方的如下性质:

/   an/2*an/2                      n为偶数时 
an
        \  a(n-1)/2*a(n-1)/2              n为奇数时

要求得n次方,我们先求得n/2次方,再把n/2的结果平方一下。如果把求n次方的问题看成一个大问题,把求n/2看成一个较小的问题。这种把大问题分解成一个或多个小问题的思路我们称之为分治法。这样求n次方就只需要logn次运算了。

参考代码:

1: #include<stdlib.h> 
2: #include<stdio.h>  
3: #include<string.h> //memcpy  
4:   
5: void multiply(int A[], int B[], int result[])   
6: {  
7:     result[0] = A[0]*B[0] + A[1]*B[2];  
8:     result[1] = A[0]*B[1] + A[1]*B[3];  
9:     result[2] = A[2]*B[0] + A[3]*B[2];
10:     result[3] = A[2]*B[1] + A[3]*B[3]; 
11: }  
12:  
13: void power(int A[], int n, int result[]) 
14: {  
15:     if (n==1)  
16:     {  
17:         memcpy(A, result, 4*sizeof(int));  
18:         return;  
19:     }  
20:     int tmp[4];
21:     power(A, n>>1, result); 
22:     multiply(result, result, tmp);  
23: 
24:     if (n & 1 == 1)  
25:     {  
26:         multiply(tmp, A, result); 
27:     }   
28:     else  
29:     { 
30:         memcpy(result, tmp, 4*sizeof(int));  
31:     }  
32: }  
33:  
34: int getNthFibonacci(int n)  
35: {  
36:     int A[4] = {1,1,1,0};
37:     int result[4]={1,1,1,0}; 
38:     power(A, n, result);
39:  
40:     return result[0]; 
41: }  
42:   
43:  
44: int main()  
45: {  
46:int n
47:     while(scanf("%d",&n)) 
48:     { 
49:         if(n==-1) 
50:             break;  
51:         if(n==0 || n==1)  
52:             printf("n=%d,result=%d\n",n,n); 
53:         else  
54:             printf("n=%d,result=%d\n",n,getNthFibonacci(n-1));
55:     } 
56:     getchar(); 
57:     return 0; 
58: }
时间: 2024-09-28 03:36:13

以最快的速度求出Fibonacci 序列的第n项的相关文章

16.有一分数序列 1/2,2/3,3/5,5/8,8/13,13/21,…求出这个序列的前200 项之和

使用向量: #include<iostream>#include<vector>using namespace std;int FenShu(int); int main(){    double sum=0,sum1=0;    for(int i=2;i<=200;i++)    {        sum1+=FenShu(i);    }    sum=sum1+0.5;    cout<<sum<<endl;    return 0;} int

使用C语言编写程序,求解有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个序列的前20项

void test() {  //思路:找规律->从3/2开始 下一个数的分母是上一个数的分子,下一个数的分子是上一个数的分子分母之和  double mol = 2.0, den = 1.0, denlast = 0;  double div = mol / den;  double sum = 0;  int i = 0;  for (i = 0; i < 20; i++)  {   printf("%g/%g ", mol, den);//%g省去浮点数的无效0   

给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当k=3时,这个序列是: 1,3,4,9,10,12,13,… (该序列实际上就是:3^0,3^1,3^0+3^1,3^2,3^0+3^2,3^1+3^2,3^0+3^1+3^2,…) 请你求出这个序列的第N项的值(用10进制数表示)。 例如,对于k=3,N=100,正确答案应该是9

只有1行,为2个正整数,用一个空格隔开: k N (k.N的含义与上述的问题描述一致,且3≤k≤15,10≤N≤1000). 计算结果,是一个正整数(在所有的测试数据中,结果均不超过2.1*10^9).(整数前不要有空格和其他符号). #include<stdio.h> int n2[1010];long long l1 = 1; long long n, k; long long sm(long long i,long long k) { long long s = 1; int j; fo

有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。

/** * @author 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和. */ public class Sum { public static void main(String[] args) { double a = 1, b = 1, c = 0, s = 0; for (int i = 0; i < 20; i++) { c = a + b; s = s + c / a; b = a; a = c; } System.out.pri

1126 求递推序列的第N项(51nod)

原题链接http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1126 这题我们应该先求出他的周期来..... for(i=3;i<300;i++) { f[i]=((A*f[i-1]+B*f[i-2])%7+7)%7; if(f[i-1]==1&&f[i]==1) break; }当f[i-1]==1&&f[i]==1时相当于又回到了开始,所以i-2就是他的周期 这里要注意当n%(i-2)==0时

【Python3练习题 019】 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。

后一个分数的分子=前一个分数的分子+分母,后一个分数的分母=前一个分数的分子,循环个20次就有结果.注意,假设分子为a,分母为b,虽然 a = a + b, 但此时a已经变成 a+b 了,所以再给b重新赋值的时候,得是 (a+b)-b 才能等于原分母b,所以重新赋值时就得写成 a-b 方法一 from fractions import Fraction def fibonacci(n): a, b = 1, 2 res = [1] i = 1 while i < n: a, b = b, a+b

2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。

package com.hanqi; public class Qiuhe { public static void main(String[] args) { // TODO 自动生成的方法存根 double sum=0,fenshu=0,a=1,b=2,c=0; for (int i = 0; i < 20; i++) { fenshu=b/a; c=a; a=b; b=a+c; sum+=fenshu; //System.out.println(fenshu); } System.out.

有一分数序列: 2/1 3/2 5/3 8/5 13/8 21/13...... 求出这个数列的前N项之和,保留两位小数。

题目描述 输入 N 输出 数列前N项和 样例输入 10 样例输出 16.48 代码:#include<stdio.h>int main(){    int i,N;    double c=0,a=2.0,b=1.0,t,sum=0;         scanf("%d",&N);    for(i=0;i<N;i++)    {           c=a/b;        sum=sum+c;        t=a;        a=a+b;     

关于1/2,3/4,7/6,13/8,21/10...求出这个数列的前20项之和

double H= 0; double a = 1, b = 2;  因为初始值为1/2 int i = 0;前多少项 for (i = 0; i < 20; i++) { H+= a / b;//后一项的分子等于前一项的分子加分母 a +=b ; b +=2 ;分母是每个都要加2 } Console.WriteLine(H); Console.WriteLine(a); Console.WriteLine(b);