Fibonacci Number modulo M and Pisano Period

Given two number N and M. The task is to find the N-th fibonacci number mod M.

In general let FN be the N-th fibonacci number then the output should be FN % M.

The Fibonacci sequence is a series of numbers in which each no. is the sum of two preceding nos. It is defined by the recurrence relation:



F0 = 0
F1 = 1
Fn = Fn-1 + Fn-2

These nos. are in the following sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …

Here N can be large.

Examples:

Input: N = 438, M = 900
Output: 44

Input: N = 1548276540, M = 235
Output: 185

Approach:
However, for such values of N, a simple recursive approach to keep calculating N Fibonacci numbers with a time complexity of O(2N) should be avoided. Even an iterative or a Dynamic Programming approach with an algorithm looping for N iterations will not be time-efficient.

This problem can be solved using the properties of Pisano Period.

For a given value of N and M >= 2, the series generated with Fi modulo M (for i in range(N)) is periodic.
The period always starts with 01.
The Pisano Period is defined as the length of the period of this series.

To understand it further, let’s see what happens when M is small:

i 0 1 2 3 4 5 6 7 8 9 10 11
Fi 0 1 1 2 3 5 8 13 21 34 55 89
Fi mod 2 0 1 1 0 1 1 0 1 1 0 1 1
Fi mod 3 0 1 1 2 0 2 2 1 0 1 1 2

For M = 2, the period is 011 and has length 3 while for M = 3 the sequence repeats after 8 nos.



Example:
So to compute, say F2019 mod 5, we’ll find the remainder of 2019 when divided by 20 (Pisano Period of 5 is 20). 2019 mod 20 is 19. Therefore, F2019 mod 5 = F19 mod 5 = 1. This property is true in general.
We need to find the remainder when N is divided by the Pisano Period of M. Then calculate F(N)remainder mod M for the newly calculated N.

Below is the implementation of FN modulo M in Python:

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 program to calculate
# Fibonacci no. modulo m using
# Pisano Period
  
# Calculate and return Pisano Period
# The length of a Pisano Period for
# a given m ranges from 3 to m * m 
def pisanoPeriod(m):
    previous, current = 0, 1
    for i in range(0, m * m):
        previous, current \
        = current, (previous + current) % m
          
        # A Pisano Period starts with 01
        if (previous == 0 and current == 1):
            return i + 1
  
# Calculate Fn mod m 
def fibonacciModulo(n, m):
      
    # Getting the period
    pisano_period = pisanoPeriod(m)
      
    # Taking mod of N with 
    # period length
    n = n % pisano_period
      
    previous, current = 0, 1
      
    for i in range(n-1):
        previous, current \
        = current, previous + current
          
    return (current % m)
  
# Driver Code
if __name__ == '__main__'
    n = 1548276540
    m = 235
    print(fibonacciModulo(n, m))

chevron_right


Output:

185

Pisano Period of 235 is 160. 1548276540 mod 160 is 60. F60 mod 235 = 185. Using Pisano Period, we now need to calculate Fibonacci nos. iteratively for a relatively lower N than specified in the original problem and then calcuate FN modulo M.

Time Complexity: O(M2)



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :
Practice Tags :


2


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.