我试图找到第n个斐波那契数字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;
}
答案 0 :(得分:2)
您遇到的错误是堆栈溢出。这是因为为您的线程分配的堆栈是1MB(默认情况下),并且您的程序具有深度为500万的递归函数调用。
为了解决这个问题,您可以反转迭代,如:
int n,i;
for(i=1;i<=max_n;++i)
{
fib(i);
}
由于fib
缓存结果,根本不会有任何递归调用,也不会抛出堆栈溢出异常。
答案 1 :(得分:0)
您编码存储std::vector
中获得的Fibonacci列表的所有值,并使fib函数添加std::vector
内的最后两个值,然后写入它。这样,您可以避免过多的递归溢出堆栈。唯一的问题是,矢量会变得很大。
答案 2 :(得分:0)
正如Tal Shalti的回答所说,一个简单的解决方案是从前到后填充你的备忘录阵列。
但是,如果将函数设计为迭代函数而不是递归函数,则可以省去专门填充Fibonacci数列表的需要。我就是这样做的:
#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();
}
答案 3 :(得分:0)
可以将诸如斐波那契的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,将需要&lt; = 23(log2(5000000))循环以将矩阵提升到幂n。对于fibonacci modulo 100000,模式重复每150000个数字,fib(n + 150000)%100000 == fib(n)%100000 == fib(n%150000)%100000。利用这一点,n%150000的最大值= 149999,最大循环次数为18(log2(149999))。