繁体   English   中英

斐波那契大数和(只打印最后一位)

[英]Fibonacci Sum of Large Numbers(Only Last Digit to be Printed)

我一直试图提出一个解决方案,解决寻找大 n 斐波那契数列总和的最后一位数字的问题。 我已经能够通过几个大 n 的测试用例。 但是我被困在以下 n = 832564823476 的情况下。我知道它可以使用 Pisano 的周期来解决,但我无法提出有效的算法。 任何帮助都会很棒。 谢谢。 我实现的代码如下-

#include <iostream>
using namespace std;


int calc_fib(int n) {

    int fib[n+1];
    fib[0]=0;
    fib[1]=1;
    int res = 1;
    for(int i = 2; i<=n;i++){
        fib[i] = (fib[i-1]%10 + fib[i-2]%10)%10;
        res = res + fib[i];
    }
    return (res%10);
}

int main() {
    int n = 0;
    std::cin >> n;

    std::cout << calc_fib(n) << '\n';
    return 0;
}

解决了

适用于所有输入范围。 它适用于以下算法。 这个想法是要注意斐波那契数的最后一位数字也出现在长度为 60 的序列中(来自上一个问题:因为 10 的 pisano peiod 是 60)。 不管 n 有多大,它的最后一位数字都会出现在序列中的某个地方。 除了最后一位数字 10 的边缘情况外,还有两件事。

  • 第 n 个斐波那契数列之和 = F(n+2) -1
  • 然后模 10 的 pisano 周期 = 让 n+2 mod (60) = m 然后找到 F(m) mod(10)-1

代码如下;

#include <iostream>
using namespace std;

long long calc_fib(long long n) {

    n = (n+2)%60;
    int fib[n+1];
    fib[0]=0;
    fib[1]=1;
    int res = 1;
    for(int i = 2; i<=n;i++){
        fib[i] = (fib[i-1]%10 + fib[i-2]%10)%10;
        // res = res + fib[i];
    }
    // cout<<fib[n]<<"\n";
    if(fib[n] == 0){
        return 9;
    }
    return (fib[n]%10-1);
}

int main() {
    long long n = 0;
    std::cin >> n;

    std::cout << calc_fib(n) << '\n';
    return 0;
}

实际上这比 Niall 的回答还要简单

int get_fibonacci_sum_last_digit(long long n) {
    const int kPisanoSize = 60;
    int rest = n % kPisanoSize;
    int preparedNumbers[kPisanoSize] = {0, 1, 2, 4, 7, 2, 0, 3, 4, 8, 3, 
        2, 6, 9, 6, 6, 3, 0, 4, 5, 0, 6, 7, 4, 2, 7, 0, 8, 9, 8, 8, 7, 
        6, 4, 1, 6, 8, 5, 4, 0, 5, 6, 2, 9, 2, 2, 5, 8, 4, 3, 8, 2, 1, 
        4, 6, 1, 8, 0, 9, 0};
    return preparedNumbers[rest];

}

如果你只需要像你说的那样输出最后一位,我想你可以利用你提到的Pisano Period ,至于模数10,循环长度只有60,你可以预先制作一个60的数组数字。

如果你想自己计算,我认为你可以使用矩阵求幂,它给你O(lg N)复杂度,在计算矩阵指数时,继续存储临时结果模 10。请参阅矩阵部分以供您参考。

对于您删除数组的函数。

#include "stdafx.h"
#include <iostream>
using namespace std;
int calc_fib(long long int n) {

    int fibzero = 0;
    int fibone = 1;
    int fibnext;
    long long int res = 1;
    for (long long int i = 2; i <= n; i++) {

        fibnext = (fibone + fibzero) % 10;
        fibzero = fibone;
        fibone = fibnext;
        res = res + fibnext;
    }
    return (res % 10);
}

int main() 
{
    long long int n = 0;
    std::cin >> n;

    std::cout << calc_fib(n) << '\n';
    return 0;
}

Fibonacci 和的最后一位数字在 60 个元素后重复。

这里的周期是 60 [0-59]。 所以要得到第n个数字总和的最后一位是第n%60个数字总和的最后一位

#include <iostream>
#include <vector>
#include <algorithm>
int get_last_digit(int n){
  std::vector<int> last_digits(60);
  long long a = 0, b = 1;
  last_digits[0] = 0;
  last_digits[1] = 1;
  long long temp, sum = 1;
  // Fill last_digits vector with the first 60 sums last digits
  for (int i = 2; i < 60; i++) {
    temp = a+b;
    a = b;
    b = temp;
    sum += temp;
    last_digits[i] = sum%10;
  }
  // Now return n%60'th element
  return last_digits[n%60];
}
int main(int argc, char const *argv[]) {
  int n;
  std::cin>>n;
  std::cout << get_last_digit(n);
  return 0;
}

解决问题的巧妙方法(我使用java)。 逻辑是利用10的pisano周期。写下Sum(F(n)) = F(n+2) + 1之间的对应关系会很有帮助。 提示:单独创建一个斐波那契数列。

private static long getFibonacciSum(long n) {
    n = (n + 2) % 60;
    long[] fib = new long[(int) n + 1];
    long cor;
    fib[0] = 0;
    fib[1] = 1;
    for (int i = 2; i <= n; i++) {
        fib[i] = (fib[i - 1] + fib[i - 2]) % 10;
    }
    if (fib[(int) n] == 0) cor = 9;
    else cor = fib[(int) n] - 1;
    return cor;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM