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: 44Input: 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:
Java
// Java program to calculate // Fibonacci no. modulo m using // Pisano Period import java.io.*; class GFG{ // Calculate and return Pisano Period // The length of a Pisano Period for // a given m ranges from 3 to m * m public static long pisano( long m) { long prev = 0 ; long curr = 1 ; long res = 0 ; for ( int i = 0 ; i < m * m; i++) { long temp = 0 ; temp = curr; curr = (prev + curr) % m; prev = temp; if (prev == 0 && curr == 1 ) res= i + 1 ; } return res; } // Calculate Fn mod m public static long fibonacciModulo( long n, long m) { // Getting the period long pisanoPeriod = pisano(m); n = n % pisanoPeriod; long prev = 0 ; long curr = 1 ; if (n == 0 ) return 0 ; else if (n == 1 ) return 1 ; for ( int i = 0 ; i < n - 1 ; i++) { long temp = 0 ; temp = curr; curr = (prev + curr) % m; prev = temp; } return curr % m; } // Driver Code public static void main(String[] args) { long n = 1548276540 ; long m = 235 ; System.out.println(fibonacciModulo(n, m)); } } // This code is contributor by Parag Pallav Singh |
Python3
# Python3 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 if n = = 0 : return 0 elif n = = 1 : return 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)) |
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 calculate FN modulo M.
Time Complexity: O(M2)
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.