我试图计算Fn mod m,其中Fn是第n个Fibonacci数。 n可能真的很大,所以以简单的方式计算Fn真的效率不高(矩阵取幂会工作)。问题陈述要求我们使用模数的分配属性执行而不用计算Fn: (a + b)mod m = [a mod m + b mod m] mod m
(在有人问我之前,我查找了同样问题的答案。但是,我想回答我的具体问题,因为我没有询问算法解决这个问题)
使用这个以及第n个Fibonacci数只是前两个的总和的事实,我不需要存储Fibonacci数,而只需要计算连续模运算的结果。在这个意义上,我应该有一个大小为n的数组F,其中存储了使用上述属性迭代计算Fn mod m的结果。我已设法使用以下代码解决此问题。然而,在审查它之后,我偶然发现了让我感到困惑的事情。
long long get_fibonacci_huge_mod(long long n, long long m) {
long long Fib[3] = {0, 1, 1};
long long result;
long long index;
long long period;
long long F[n+1];
F[0] = 0;
F[1] = 1;
F[2] = 1;
for (long long i = 3; i <= n; i++) {
F[i] = (F[i-2] + F[i-1]) % m;
if (F[i] == 0 && F[i+1] == 1 && F[i+2] == 1) {
period = i;
break;
}
}
index = n % period;
result = F[index];
return result;
}
此解决方案输出任何n和m的正确结果,即使它们非常大。当n很大时,它可能会有点慢,但我现在并不担心。我有兴趣以这种方式专门解决问题。我将尝试使用矩阵求幂或任何其他更快的算法稍后来解决它。
所以我的问题如下。在代码的开头,我创建了一个大小为n + 1的数组F.然后我使用分布属性迭代计算Fn mod m的数组。写完这个循环后让我感到困惑的一件事是,由于F被初始化为全零,如何正确使用F [i + 2],F [i + 1],如果他们没有&#39;是否已计算?我认为它们被正确使用,因为算法每次输出正确结果。也许这个假设是错的?
我的问题不在于算法本身,我在询问内部循环中的内容。
谢谢
答案 0 :(得分:1)
这是正确算法的错误实现。让我们先看一下修正后的版本。
long long get_fibonacci_huge_mod(long long n, long long m) {
long long result;
long long index;
long long period = n+1;
long long sz = min (n+1,m*m+1); // Bound for period
long long *F = new long long[sz];
F[0] = 0;
F[1] = 1;
F[2] = 1;
for (long long i = 3; i < sz; i++) {
F[i] = (F[i-2] + F[i-1]) % m;
if (F[i] == 1 && F[i-1] == 0) { // we have got back to where we started
period = i-1;
break;
}
}
index = n % period;
result = F[index];
delete[]F;
return result;
}
为什么原始代码有效?因为你很幸运由于数组初始化为幸运垃圾,对i + 1和i + 2的检查从未评估为真。结果,这减少了对F(n)的幼稚评价而没有结合周期性。