用于大数的Fibonacci算法

时间:2014-11-06 23:33:09

标签: c++ algorithm fibonacci

寻找解决斐波那契问题的好算法 递归方式给了我超出时间限制

示例输入: 70007 样品输出(最后一位数): 3

5 个答案:

答案 0 :(得分:2)

这更像是一个数学问题,最近也发布了类似的问题。 Fibonacci数可以被认为是线性递归方程(递归定义)。在这种情况下,F(n)= F(n-1)+ F(n-2)。使用数组f表示F(n)和F(n-1),其矩阵形式为:

       | 1  1 |
   a = | 1  0 |

       | 1 |
f(2) = | 1 |

f(i+1) = a f(i)

f(i+j) = a^j f(i)

这是基于F(0)= 0,F(1)= 1,F(2)= 1,F(3)= 2,F(4)= 3,F(5)= 5,F (6)= 8,......

要加快此过程,请使用重复平方将矩阵a提升到幂j。例如,a ^ 7 =(a * a ^ 2 * a ^ 4)。对于32位n,循环数为32.对于64位n,循环数为64。

然而,由于只要求最后一个数字,你做数学模10并且数学模10完成,结果证明a ^(j%60)= a ^ j(这是用a确定的)程序)。

f(i+j) = a^(j%60) f(i)

所以计算^(j%60)的循环次数最多为6.在我的系统上,计算任何32位或64位无符号整数n的fib(n)%10需要不到2微秒因为实际计算是f(n)=(a ^((n-2)%60)f(2))%10(所有数学运算都完成%10)。

这可以通过简单地索引包含f(0)到f(59)的最后一个数字的60个字符的预生成数组,然后将数组索引(n%60)来进一步加速。如果生成数组所花费的时间计算为计算时间的一部分,则一次性矩阵计算(最多6次循环)应该更快。

matix可以被反转并用于计算负的斐波纳契值,这些值具有相同的幅度,但具有交替的符号:

         |  0  1  |
a^(-1) = |  1 -1  |

f(-6) = -8
f(-5) =  5
f(-4) = -3
f(-3) =  2
f(-2) = -1
f(-1) =  1
f( 0) =  0
f( 1) =  1
f( 2) =  1
f( 3) =  2
f( 4) =  3
f( 5) =  5
f( 6) =  8

如果没有模10,那么最大的32位无符号值是f(47)= 2971215073,最大的64位无符号值是f(93)= 12200160415121876738。

答案 1 :(得分:2)

如果您只需要最后一位数字,那么会有更快的方法,如示例输出中所示。由于我们正在查看最后一位数字,因此在我们开始重复之前,可能性有限。如果我们取f(1)= 1且f(2)= 1,则注意f(61)= 1而f(62)= 1是第一个重复对。换句话说,Fibonacci数的最后一位是一个长度为60的循环。计算前60位并将它们存储在一个数组中,然后返回数组的n mod 60元素。恒定时间。

答案 2 :(得分:1)

这里有两个问题。

  1. 递归太慢了。不能慢。使用迭代算法或其中一个更快的算法。你不能使用例如Binet算法一步为您提供答案,因为它会为n=70007产生FP无穷大。
  2. 70007 th Fibonacci数的整数(或长)溢出。您需要使用迭代算法,但每次只记住最后一位数字。最后两个Fibonacci数的最后数字之和(模10)仍然给出下一个Fibonacci数的最后一位数。

答案 3 :(得分:1)

只需计算Fib数directly。我记得通过使用floor功能可以简化确切的公式,但我留给你研究这些问题。总结:直接公式很好。

答案 4 :(得分:-1)

#include <stdio.h>
#include <stdlib.h>

/*
 * By Nedal Kouissi
 * Fibonacci
 * The Rfibonacci means that function use a recursive methode
 * the Ifibonacci means that function use an iteration methode
 */
// finction prototype
unsigned long long int Ifibonacci( unsigned int ); 
// function prototype
unsigned long long int Rfibonacci( unsigned int );

int main(int argc, char** argv) {
    unsigned int f = 1000000000000;

    // display the results
    printf( "Fibonacci( %u ) = %llu\n", f, Ifibonacci( f ) );

    return (EXIT_SUCCESS);
}

unsigned long long int Ifibonacci( unsigned int x ) {
    if ( x == 0 || x == 1 )
        return x;

    unsigned int i;
    int prevP = 0;
    int prev = 1;
    int result;

    for ( i = 2; i <= x ; ++i ) {
        result = prevP + prev;
        prevP = prev;
        prev = result;
    } // end for

    return result;
} // end function Ifibonacci

unsigned long long int Rfibonacci( unsigned int x ) {
    if ( x == 0 || x == 1 )
        return x;
    else // recursive step
        return Rfibonacci( x - 1 ) + Rfibonacci( x - 2 );

} // end function Rfibonacci