查找第n个斐波那契数时出错

Error in finding nth fibonacci number

本文关键字:出错 查找      更新时间:2023-10-16

我试图找到第n个fibonacci数mod 100000,其中n可以高达5000000。

这是我的代码:

#define max_n 5000000
int mod = 100000;
int memo[max_n + 5];
int fib (int n)
{
      if (n == 1) 
           return 0;
      if (n == 2) 
           return 1;
      if (memo[n] > 0) 
           return memo[n];
      memo[n]=(fib(n-1) + fib(n-2))%mod;
      return memo[n];
}

但当我运行代码时。它给出了运行时错误。请帮助

主要:

#include <iostream>
using namespace std;
int main()
{
int n, i;
for (i = max_n; i >= 1 ;i--)
{
    fib (i);
}
cin >> n;
cout << memo[n] << endl;
return 0;
}

您得到的错误是堆栈溢出。这是因为为线程分配的堆栈是1MB(默认情况下),并且程序有一个深度为500万的递归函数调用。

为了解决这个问题,你可以反向迭代,比如:

int n,i;
for(i=1;i<=max_n;++i)
{
   fib(i);
}

由于fib缓存结果,因此根本不会有任何递归调用,也不会引发堆栈溢出异常。

您可以将获得的Fibonacci列表的所有值存储在std::vector中,并使fib函数将std::vector中的最后两个值相加,然后对其进行写入。这样,就可以避免过多的递归溢出堆栈。唯一的问题是,矢量会变得很大。

正如Tal Shalti的回答所说,一个简单的解决方案是从前到后填充备忘录数组。

然而,如果您将函数设计为迭代的,而不是递归的,则可以消除专门填充斐波那契数列表的需要。以下是我的做法:

#include <iostream>
#include <vector>
#include <cassert>
#define CACHE_FIB
using namespace std;
const int MOD = 100000;
vector<int> MEMO{0, 1};
int fib_mod(size_t n) {
    assert(n > 0);
    n -= 1; // zero based
    if(n < MEMO.size())
        return MEMO[n];
    for(size_t i = MEMO.size() - 1; i < n; i++) {
        int next = (MEMO[MEMO.size() - 1] + MEMO[MEMO.size() - 2]) % MOD;
        MEMO.push_back(next);
    }
    return MEMO.back();
}

像斐波那契这样的LRE(线性递归方程)可以转换为矩阵乘法。在这种情况下:

F(0) =  |  0  |   (fib( 0))
        |  1  |   (fib(-1))
M =     | 1 1 |   (calculates LRE             to new 1st number)
        | 1 0 |   (copies previous 1st number to new 2nd number)
F(n) = M F(n-1) = matrixpower(M, n) F(0)

您可以通过使用重复平方(有时称为二进制求幂)将矩阵提高到n的幂。整数示例代码:

    r = 1;             /* result */
    s = m;             /* s = squares of integer m */
    while(n){          /* while exponent != 0 */
        if(n&1)        /*   if bit of exponent set */
            r *= s;    /*     multiply by s */
        s *= s;        /*   s = s squared */
        n >>= 1;       /*   test next exponent bit */
    }

所有这些都将以100000为模完成。对于n<=5000000,则需要<=23(log2(5000000))循环以将矩阵提升到n的幂。对于fibonacci模100000,该模式每150000个数字重复一次,fib(n+150000)%100000==fib(n)%100000===fib(n=150000)%100000。利用这一点,n%150000的最大值=149999,循环的最大数量为18(log2(149999))。