【问题标题】:Computing fibonacci like function in sublinear time在亚线性时间内计算类斐波那契函数
【发布时间】:2016-05-20 23:21:04
【问题描述】:

那么,问题来了:

给定一个数字 n,我需要计算它需要递归计算该数字的斐波那契的调用量,并且只输出给定基数中的最后一位数字作为小数。输入有 2 个数字,第一个是数字 n,第二个是输出的基数。输出应该是案例编号、第一个输入、第二个输入和计算结果。当第一个条目等于等于 0 的第二个条目时,程序应该退出。例如:

输入:
0 100
1 100
2 100
3 100
10 10
3467 9350
0 0

输出:
案例一:0 100 1
案例 2:1 100 1
案例 3:2 100 3
案例 4:3 100 5
案例 5:10 10 7
案例6:3467 9350 7631

在尝试解决这个问题时,我已经得出了以下公式。作为 c(n) 以 b 为底的调用次数的最后一位,我们有:

c(n) = (c(n-1) + c(n-2) + 1) mod b

问题是 n 可以是 0 到 2^63 - 1 之间的任何值,所以我真的需要代码高效。我尝试过以迭代方式或使用动态编程,但是,虽然它给了我正确的输出,但它并没有在足够短的时间内给我。这是我的代码:

迭代

#include <iostream>
#include <vector>

using namespace std;

int main(){
    vector<unsigned long long int> v;
    unsigned long long int x,y,co=0;
    cin >> x >> y;
    while(x||y){
        co++;
        v.push_back(1);
        v.push_back(1);
        for(int i=2;i<=x;i++) v.push_back((v[i-1]+v[i-2]+1)%y);
        cout << "Case " << co << ": " << x << " " << y << " " << v[x] << endl;
        cin >> x >> y;
        v.clear();
    }
    return 0;
}

动态编程

#include <iostream>
#include <vector>

using namespace std;

vector<unsigned long long int> v;

unsigned long long c(int x, int y){
    if(v.size()-1 < x) v.push_back((c(x-1,y) + c(x-2,y) + )%y);
    return v[x];
}

int main(){
    int x,y,co=0;
    cin >> x >> y;
    while(x||y){
        co++;
        v.push_back(1);
        v.push_back(1);
        cout << "Case " << co << ": " << x << " " << y << " " << c(x,y) << endl;
        cin >> x >> y;
        v.clear();
    }
    return 0;
}

x 和 y 分别是 n 和 b,v 保存 c(n) 的值

【问题讨论】:

  • 如果有帮助,朴素的斐波那契算法需要 2F_{n+1} - 1 次调用来评估 F_n。也许你可以以某种方式使用它?
  • 谢谢,我想这会让我的工作减半
  • 通过 @templatetypedef 的观察,您的问题被简化为找到 F_{n+1} mod b。关于如何做到这一点,已经有很多关于 s-o 的答案。这似乎是一个合理的选择(尽管在 java 而不是 C++ 中):stackoverflow.com/questions/20300537/…
  • “b”的范围是多少? @Beta 有一个可能很好的答案(尽管我个人会在链接的问题中使用矩阵求幂方法)——但只有在 b 保证较小的情况下,Beta 方法才有效。
  • b 最高可达 10000

标签: c++ algorithm performance fibonacci


【解决方案1】:

序列中的每个 c 都小于 b。所以 a c 的值有 b 种可能性。所以一对连续的元素 [ck, ck+1] 可以有 b2 个可能的值。所以如果你从头开始计算 c1, c2, c3... 你最多只能计算 b2 在序列开始重复之前;你会得到一个 [ck, ck+1] 等于早先的 [cj, cj +1]。

那么你知道循环的长度,称它为S,你知道cn = c((n-j)mod S)+j 对于所有n > j。这应该会大大减少您的工作量。

【讨论】:

  • 这是一个很好的答案,具体取决于 b 的范围(问题中没有给出)。如果 b 可以很大,那就不好了。如果 b 总是很小,那很好。
  • 对于问题b可以大到10000所以我猜是可行的
猜你喜欢
  • 2013-03-31
  • 2014-12-28
  • 1970-01-01
  • 2016-08-26
  • 2010-12-04
  • 2016-08-04
  • 2020-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多