[英]Error in finding nth fibonacci number
我試圖找到第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;
}
您得到的錯誤是堆棧溢出。 這是由於為您的線程分配的堆棧為1MB(默認情況下),並且您的程序具有深度為500萬的遞歸函數調用。
為了解決此問題,您可以像這樣反轉迭代:
int n,i;
for(i=1;i<=max_n;++i)
{
fib(i);
}
由於fib
緩存了結果,因此根本不會進行任何遞歸調用,也不會引發堆棧溢出異常。
你代碼存儲你在得到斐波那契列表中的所有值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。 對於以100000為模的斐波那契模,該模式每150000個數字重復一次,即fib(n + 150000)%100000 == fib(n)%100000 == fib(n%150000)%100000。 利用此優勢,n%150000 = 149999的最大值,最大循環數為18(log2(149999))。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.