📜  斐波那契数列给定范围内的数字总和的最后一位

📅  最后修改于: 2021-05-04 09:12:56             🧑  作者: Mango

给定两个表示范围[M,N]的非负整数M,N ,其中M≤N,任务是找到F M + F M + 1 …+ F N之和的最后一位,其中F K为斐波那契数列中的K斐波那契数。

例子:

朴素方法:针对此问题的朴素方法是一个一个地找出所有K斐波那契数的和,其中K处于[M,N]范围内,并最后返回总和的最后一位。此方法的时间复杂度为O(N),并且该方法对于N的高阶值失败。
高效方法:针对此问题的有效方法是使用皮萨诺时期的概念。

  • 这个想法是分别计算(M – 1)N个斐波那契数之和,然后减去计算值的最后一位。
  • 这是因为所有K个第Fibonacci数之和的最后一位数字,使得K处于[M,N]范围内等于该范围内所有KFibonacci数之和的最后一位数字之差。 [0,N]以及所有第K斐波纳契数的总和,范围为[0,M – 1]
  • 这些值可以分别在很短的时间内通过皮萨诺时期的概念来计算。
  • 让我们了解皮萨诺时期的运作方式。下表说明了前10个斐波纳契数以及在对这些数执行模2运算时获得的值。
i 0 1 2 3 4 5 6 7 8 9 10
Fi 0 1 1 2 3 5 8 13 21 34 55
Fi mod 2 0 1 1 0 1 1 0 1 1 0 10
  • 显然,皮萨诺周期(F为i mod 2)为3,因为011重复本身和长度(011)= 3。
  • 现在,让我们观察以下身份:
  • 因此,在给定F i mod 10的Pisano周期为60的情况下,我们只计算总和直到剩下的余数,而不是计算范围[0,N]中所有数字的总和的最后一位。

下面是上述方法的实现:

C++
// C++ program to calculate
// last digit of the sum of the
// fibonacci numbers from M to N
#include
using namespace std;
 
// Calculate the sum of the first
// N Fibonacci numbers using Pisano
// period
long long fib(long long n)
{
     
    // The first two Fibonacci numbers
    long long f0 = 0;
    long long f1 = 1;
 
    // Base case
    if (n == 0)
        return 0;
    if (n == 1)
        return 1;
    else
    {
        // Pisano period for % 10 is 60
        long long rem = n % 60;
 
        // Checking the remainder
        if(rem == 0)
           return 0;
 
        // The loop will range from 2 to
        // two terms after the remainder
        for(long long i = 2; i < rem + 3; i++)
        {
           long long f = (f0 + f1) % 60;
           f0 = f1;
           f1 = f;
        }
         
        long long s = f1 - 1;
        return s;
    }
}
 
// Driver Code
int main()
{
    long long m = 10087887;
    long long n = 2983097899;
 
    long long final = abs(fib(n) - fib(m - 1));
    cout << final % 10 << endl;
}
 
// This code is contributed by Bhupendra_Singh


Java
// Java program to calculate
// last digit of the sum of the
// fibonacci numbers from M to N
import java.util.*;
 
class GFG{
 
// Calculate the sum of the first
// N Fibonacci numbers using Pisano
// period
static int fib(long n)
{
     
    // The first two Fibonacci numbers
    int f0 = 0;
    int f1 = 1;
 
    // Base case
    if (n == 0)
        return 0;
    if (n == 1)
        return 1;
    else
    {
         
        // Pisano period for % 10 is 60
        int rem = (int) (n % 60);
 
        // Checking the remainder
        if(rem == 0)
        return 0;
 
        // The loop will range from 2 to
        // two terms after the remainder
        for(int i = 2; i < rem + 3; i++)
        {
           int f = (f0 + f1) % 60;
           f0 = f1;
           f1 = f;
        }
         
        int s = f1 - 1;
        return s;
    }
}
 
// Driver Code
public static void main(String args[])
{
    int m = 10087887;
    long n = 2983097899L;
    int Final = (int)Math.abs(fib(n) -
                              fib(m - 1));
     
    System.out.println(Final % 10);
}
}
 
// This code is contributed by AbhiThakur


Python3
# Python3 program to calculate
# Last Digit of the sum of the
# Fibonacci numbers from M to N
 
# Calculate the sum of the first
# N Fibonacci numbers using Pisano
# period
def fib(n):
 
    # The first two Fibonacci numbers
    f0 = 0
    f1 = 1
 
    # Base case
    if (n == 0):
        return 0
    if (n == 1):
        return 1
    else:
 
        # Pisano Period for % 10 is 60
        rem = n % 60
 
        # Checking the remainder
        if(rem == 0):
            return 0
 
        # The loop will range from 2 to
        # two terms after the remainder
        for i in range(2, rem + 3):
            f =(f0 + f1)% 60
            f0 = f1
            f1 = f
 
        s = f1-1
        return(s)
 
# Driver code
if __name__ == '__main__':
     
    m = 10087887
    n = 2983097899
 
    final = fib(n)-fib(m-1)
 
    print(final % 10)


C#
// C# program to calculate
// last digit of the sum of the
// fibonacci numbers from M to N
using System;
 
class GFG{
 
// Calculate the sum of the first
// N fibonacci numbers using Pisano
// period
static int fib(long n)
{
     
    // The first two fibonacci numbers
    int f0 = 0;
    int f1 = 1;
 
    // Base case
    if (n == 0)
        return 0;
    if (n == 1)
        return 1;
    else
    {
         
        // Pisano period for % 10 is 60
        int rem = (int)(n % 60);
 
        // Checking the remainder
        if(rem == 0)
           return 0;
 
        // The loop will range from 2 to
        // two terms after the remainder
        for(int i = 2; i < rem + 3; i++)
        {
           int f = (f0 + f1) % 60;
           f0 = f1;
           f1 = f;
        }
         
        int s = f1 - 1;
        return s;
    }
}
 
// Driver Code
public static void Main()
{
    int m = 10087887;
    long n = 2983097899L;
    int Final = (int)Math.Abs(fib(n) -
                              fib(m - 1));
     
    Console.WriteLine(Final % 10);
}
}
 
// This code is contributed by Code_Mech


Javascript


输出:
5

时间复杂度: O(1) ,因为此代码对于任何输入数字都将运行近60次。