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: 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:
C++
// C++ program to calculate // Fibonacci no. modulo m using // Pisano Period #include <bits/stdc++.h> using namespace std; // Calculate and return Pisano Period // The length of a Pisano Period for // a given m ranges from 3 to m * m 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 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 int main() { long n = 1548276540; long m = 235; cout << (fibonacciModulo(n, m)); return 0; } // This code is contributed by subhammahato348 |
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)) |
C#
// C# program to calculate // Fibonacci no. modulo m using // Pisano Period using System; 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() { long n = 1548276540; long m = 235; Console.Write(fibonacciModulo(n, m)); } } // This code is contributed by subham348. |
Javascript
<script> // javascript 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 function pisano(m) { let prev = 0; let curr = 1; let res = 0; for (let i = 0; i < m * m; i++) { let temp = 0; temp = curr; curr = (prev + curr) % m; prev = temp; if (prev == 0 && curr == 1) res = i + 1; } return res; } // Calculate Fn mod m function fibonacciModulo(n,m) { // Getting the period let pisanoPeriod = pisano(m); n = n % pisanoPeriod; let prev = 0; let curr = 1; if (n == 0) return 0; else if (n == 1) return 1; for (let i = 0; i < n - 1; i++) { let temp = 0; temp = curr; curr = (prev + curr) % m; prev = temp; } return curr % m; } let n = 1548276540; let m = 235; document.write(fibonacciModulo(n, m)); // This code is contributed by vaibhavrabadiya117. </script> |
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)
Auxiliary Space: O(1)
Please Login to comment...