Fast Doubling method to find the Nth Fibonacci number
Given an integer N, the task is to find the N-th Fibonacci numbers.
Examples:
Input: N = 3
Output: 2
Explanation:
F(1) = 1, F(2) = 1
F(3) = F(1) + F(2) = 2
Input: N = 6
Output: 8
Approach:
- The Matrix Exponentiation Method is already discussed before. The Doubling Method can be seen as an improvement to the matrix exponentiation method to find the N-th Fibonacci number although it doesn’t use matrix multiplication itself.
- The Fibonacci recursive sequence is given by
F(n+1) = F(n) + F(n-1)
- The Matrix Exponentiation method uses the following formula
- The method involves costly matrix multiplication and moreover Fn is redundantly computed twice.
On the other hand, Fast Doubling Method is based on two basic formulas:
F(2n) = F(n)[2F(n+1) – F(n)] F(2n + 1) = F(n)2+F(n+1)2
- Here is a short explanation of the above results:
Start with:
F(n+1) = F(n) + F(n-1) &
F(n) = F(n)
It can be rewritten in the matrix form as:
For doubling, we just plug in “2n” into the formula:
Substituting F(n-1) = F(n+1)- F(n) and after simplification we get,
Below is the implementation of the above approach:
C++
// C++ program to find the Nth Fibonacci // number using Fast Doubling Method #include <bits/stdc++.h> using namespace std; int a, b, c, d; #define MOD 1000000007 // Function calculate the N-th fibonacci // number using fast doubling method void FastDoubling( int n, int res[]) { // Base Condition if (n == 0) { res[0] = 0; res[1] = 1; return ; } FastDoubling((n / 2), res); // Here a = F(n) a = res[0]; // Here b = F(n+1) b = res[1]; c = 2 * b - a; if (c < 0) c += MOD; // As F(2n) = F(n)[2F(n+1) – F(n)] // Here c = F(2n) c = (a * c) % MOD; // As F(2n + 1) = F(n)^2 + F(n+1)^2 // Here d = F(2n + 1) d = (a * a + b * b) % MOD; // Check if N is odd // or even if (n % 2 == 0) { res[0] = c; res[1] = d; } else { res[0] = d; res[1] = c + d; } } // Driver code int main() { int N = 6; int res[2] = { 0 }; FastDoubling(N, res); cout << res[0] << "\n" ; return 0; } |
Java
// Java program to find the Nth Fibonacci // number using Fast Doubling Method class GFG{ // Function calculate the N-th fibonacci // number using fast doubling method static void FastDoubling( int n, int []res) { int a, b, c, d; int MOD = 1000000007 ; // Base Condition if (n == 0 ) { res[ 0 ] = 0 ; res[ 1 ] = 1 ; return ; } FastDoubling((n / 2 ), res); // Here a = F(n) a = res[ 0 ]; // Here b = F(n+1) b = res[ 1 ]; c = 2 * b - a; if (c < 0 ) c += MOD; // As F(2n) = F(n)[2F(n+1) – F(n)] // Here c = F(2n) c = (a * c) % MOD; // As F(2n + 1) = F(n)^2 + F(n+1)^2 // Here d = F(2n + 1) d = (a * a + b * b) % MOD; // Check if N is odd // or even if (n % 2 == 0 ) { res[ 0 ] = c; res[ 1 ] = d; } else { res[ 0 ] = d; res[ 1 ] = c + d; } } // Driver code public static void main(String []args) { int N = 6 ; int res[] = new int [ 2 ]; FastDoubling(N, res); System.out.print(res[ 0 ]); } } // This code is contributed by rock_cool |
Python3
# Python3 program to find the Nth Fibonacci # number using Fast Doubling Method MOD = 1000000007 # Function calculate the N-th fibonacci # number using fast doubling method def FastDoubling(n, res): # Base Condition if (n = = 0 ): res[ 0 ] = 0 res[ 1 ] = 1 return FastDoubling((n / / 2 ), res) # Here a = F(n) a = res[ 0 ] # Here b = F(n+1) b = res[ 1 ] c = 2 * b - a if (c < 0 ): c + = MOD # As F(2n) = F(n)[2F(n+1) – F(n)] # Here c = F(2n) c = (a * c) % MOD # As F(2n + 1) = F(n)^2 + F(n+1)^2 # Here d = F(2n + 1) d = (a * a + b * b) % MOD # Check if N is odd # or even if (n % 2 = = 0 ): res[ 0 ] = c res[ 1 ] = d else : res[ 0 ] = d res[ 1 ] = c + d # Driver code N = 6 res = [ 0 ] * 2 FastDoubling(N, res) print (res[ 0 ]) # This code is contributed by divyamohan123 |
C#
// C# program to find the Nth Fibonacci // number using Fast Doubling Method using System; class GFG{ // Function calculate the N-th fibonacci // number using fast doubling method static void FastDoubling( int n, int []res) { int a, b, c, d; int MOD = 1000000007; // Base Condition if (n == 0) { res[0] = 0; res[1] = 1; return ; } FastDoubling((n / 2), res); // Here a = F(n) a = res[0]; // Here b = F(n+1) b = res[1]; c = 2 * b - a; if (c < 0) c += MOD; // As F(2n) = F(n)[2F(n+1) – F(n)] // Here c = F(2n) c = (a * c) % MOD; // As F(2n + 1) = F(n)^2 + F(n+1)^2 // Here d = F(2n + 1) d = (a * a + b * b) % MOD; // Check if N is odd // or even if (n % 2 == 0) { res[0] = c; res[1] = d; } else { res[0] = d; res[1] = c + d; } } // Driver code public static void Main() { int N = 6; int []res = new int [2]; FastDoubling(N, res); Console.Write(res[0]); } } // This code is contributed by Code_Mech |
Javascript
<script> // Javascript program to find the Nth Fibonacci // number using Fast Doubling Method let a, b, c, d; let MOD = 1000000007; // Function calculate the N-th fibonacci // number using fast doubling method function FastDoubling(n, res) { // Base Condition if (n == 0) { res[0] = 0; res[1] = 1; return ; } FastDoubling(parseInt(n / 2, 10), res); // Here a = F(n) a = res[0]; // Here b = F(n+1) b = res[1]; c = 2 * b - a; if (c < 0) c += MOD; // As F(2n) = F(n)[2F(n+1) – F(n)] // Here c = F(2n) c = (a * c) % MOD; // As F(2n + 1) = F(n)^2 + F(n+1)^2 // Here d = F(2n + 1) d = (a * a + b * b) % MOD; // Check if N is odd // or even if (n % 2 == 0) { res[0] = c; res[1] = d; } else { res[0] = d; res[1] = c + d; } } let N = 6; let res = new Array(2); res.fill(0); FastDoubling(N, res); document.write(res[0]); </script> |
8
Time Complexity: Repeated squaring reduces time from linear to logarithmic . Hence, with constant time arithmetic, the time complexity is O(log n).
Auxiliary Space: O(n).
Iterative Version
We can implement iterative version of above method, by initializing array with two elements f = [F(0), F(1)] = [0, 1] and iteratively constructing F(n), on every step we will transform f into [F(2i), F(2i+1)] or [F(2i+1), F(2i+2)] , where i corresponds to the current value of i stored in f = [F(i), F(i+1)].
Approach:
- Create array with two elements f = [0, 1] , which represents [F(0), F(1)] .
- For finding F(n), iterate over binary representation of n from left to right, let kth bit from left be bk .
- Iteratively apply the below steps for all bits in n .
- Using bk we will decide whether to transform f = [F(i), F(i+1)] into [F(2i), F(2i+1)] or [F(2i+1), F(2i+2)] .
if bk == 0: f = [F(2i), F(2i+1)] = [F(i){2F(i+1)-F(i)}, F(i+1)2+F(i)2] if bk == 1: f = [F(2i+1), F(2i+2)] = [F(i+1)2+F(i)2, F(i+1){2F(i)+F(i+1)}] where, F(i) and F(i+1) are current values stored in f.
- return f[0] .
Example: for n = 13 = (1101)2 b = 1 1 0 1 [F(0), F(1)] -> [F(1), F(2)] -> [F(3), F(4)] -> [F(6), F(7)] -> [F(13), F(14)] [0, 1] -> [1, 1] -> [2, 3] -> [8, 13] -> [233, 377]
Below is the implementation of the above approach:
C++
// C++ program to find the Nth Fibonacci // number using Fast Doubling Method iteratively #include <bitset> #include <iostream> #include <string> using namespace std; // helper function to get binary string string decimal_to_bin( int n) { // use bitset to get binary string string bin = bitset< sizeof ( int ) * 8>(n).to_string(); auto loc = bin.find( '1' ); // remove leading zeros if (loc != string::npos) return bin.substr(loc); return "0" ; } // computes fib(n) iteratively using fast doubling method long long fastfib( int n) { string bin_of_n = decimal_to_bin(n); // binary string of n long long f[] = { 0, 1 }; // [F(i), F(i+1)] => i=0 for ( auto b : bin_of_n) { long long f2i1 = f[1] * f[1] + f[0] * f[0]; // F(2i+1) long long f2i = f[0] * (2 * f[1] - f[0]); // F(2i) if (b == '0' ) { f[0] = f2i; // F(2i) f[1] = f2i1; // F(2i+1) } else { f[0] = f2i1; // F(2i+1) f[1] = f2i1 + f2i; // F(2i+2) } } return f[0]; } int main() { int n = 13; long long fib = fastfib(n); cout << "F(" << n << ") = " << fib << "\n" ; } |
Java
// Java program to find the Nth Fibonacci // number using Fast Doubling Method iteratively import java.io.*; class GFG { // Helper function to convert decimal to binary. static String convertToBinary( int x) { int bin = 0 ; int rem, i = 1 , step = 1 ; while (x != 0 ) { rem = x % 2 ; x = x / 2 ; bin = bin + rem * i; i = i * 10 ; } return Integer.toString(bin); } // helper function to get binary string static String decimal_to_bin( int n) { // use bitset to get binary string String bin = convertToBinary(n); int loc = bin.indexOf( "1" ); // remove leading zeros if (loc != - 1 ) { return bin.substring(loc); } return "0" ; } // computes fib(n) iteratively using fast doubling // method static int fastfib( int n) { String bin_of_n = decimal_to_bin(n); // binary string of n int [] f = { 0 , 1 }; // [F(i), F(i+1)] => i=0 for ( int i = 0 ; i < bin_of_n.length(); i++) { int b = bin_of_n.charAt(i); int f2i1 = f[ 1 ] * f[ 1 ] + f[ 0 ] * f[ 0 ]; // F(2i+1) int f2i = f[ 0 ] * ( 2 * f[ 1 ] - f[ 0 ]); // F(2i) if (b == '0' ) { f[ 0 ] = f2i; // F(2i) f[ 1 ] = f2i1; // F(2i+1) } else { f[ 0 ] = f2i1; // F(2i+1) f[ 1 ] = f2i1 + f2i; // F(2i+2) } } return f[ 0 ]; } public static void main(String[] args) { int n = 13 ; int fib = fastfib(n); System.out.print( "F(" + n + ") = " + fib); } } // This code is contributed by lokeshmvs21. |
Python3
# Python3 program to find the Nth Fibonacci # number using Fast Doubling Method iteratively def fastfib(n): """computes fib(n) iteratively using fast doubling method""" bin_of_n = bin (n)[ 2 :] # binary string of n f = [ 0 , 1 ] # [F(i), F(i+1)] => i=0 for b in bin_of_n: f2i1 = f[ 1 ] * * 2 + f[ 0 ] * * 2 # F(2i+1) f2i = f[ 0 ] * ( 2 * f[ 1 ] - f[ 0 ]) # F(2i) if b = = '0' : f[ 0 ], f[ 1 ] = f2i, f2i1 # [F(2i), F(2i+1)] else : f[ 0 ], f[ 1 ] = f2i1, f2i1 + f2i # [F(2i+1), F(2i+2)] return f[ 0 ] n = 13 fib = fastfib(n) print (f 'F({n}) =' , fib) |
C#
using System; using System.Collections.Generic; // C# program to find the Nth Fibonacci // number using Fast Doubling Method iteratively public class GFG { // Helper function to convert decimal to binary. public static string convertToBinary( int x) { int bin = 0; int rem, i = 1, step = 1; while (x != 0) { rem = x % 2; x = x / 2; bin = bin + rem * i; i = i * 10; } return bin.ToString(); } // helper function to get binary string public static string decimal_to_bin( int n) { // use bitset to get binary string string bin = convertToBinary(n); int loc = bin.IndexOf( '1' ); // remove leading zeros if (loc != -1) { return bin.Substring(loc); } return "0" ; } // computes fib(n) iteratively using fast doubling // method public static int fastfib( int n) { string bin_of_n = decimal_to_bin(n); // binary string of n int [] f = { 0, 1 }; // [F(i), F(i+1)] => i=0 for ( int i = 0; i < bin_of_n.Length; i++) { int b = bin_of_n[i]; int f2i1 = f[1] * f[1] + f[0] * f[0]; // F(2i+1) int f2i = f[0] * (2 * f[1] - f[0]); // F(2i) if (b == '0' ) { f[0] = f2i; // F(2i) f[1] = f2i1; // F(2i+1) } else { f[0] = f2i1; // F(2i+1) f[1] = f2i1 + f2i; // F(2i+2) } } return f[0]; } static public void Main() { int n = 13; int fib = fastfib(n); Console.WriteLine( "F(" + n + ") = " + fib); } } // This code is contributed by akashish__ |
Javascript
// JavaScript program to find the Nth Fibonacci // number using Fast Doubling Method iteratively // Helper function to convert decimal to binary. function convertToBinary(x) { let bin = 0; let rem, i = 1, step = 1; while (x != 0) { rem = x % 2; x = parseInt(x / 2); bin = bin + rem * i; i = i * 10; } // let myArr = Array.from(String(bin).split("")); return bin.toString(); } // helper function to get binary string function decimal_to_bin(n) { // use bitset to get binary string let bin = convertToBinary(n); let loc = bin.indexOf( '1' ); // remove leading zeros if (loc != -1) return bin.substring(loc); return "0" ; } // computes fib(n) iteratively using fast doubling method function fastfib(n) { let bin_of_n = decimal_to_bin(n); // binary string of n let f = [0, 1]; // [F(i), F(i+1)] => i=0 for (let i = 0; i < bin_of_n.length; i++){ let b = bin_of_n[i]; let f2i1 = f[1] * f[1] + f[0] * f[0]; // F(2i+1) let f2i = f[0] * (2 * f[1] - f[0]); // F(2i) if (b == '0' ) { f[0] = f2i; // F(2i) f[1] = f2i1; // F(2i+1) } else { f[0] = f2i1; // F(2i+1) f[1] = f2i1 + f2i; // F(2i+2) } } return f[0]; } let n = 13; let fib = fastfib(n); console.log( "F(" ,n, ") =" , fib); // The code is contributed by Gautam goel (gautamgoel962) |
F(13) = 233
Time Complexity: We are iterating over a binary string of length n and doing constant time arithmetic operations for each digit, so the time complexity is O(n).
Auxiliary Space: We are storing two elements in f (which is a constant cost), and the binary representation of the number (which has a cost of O(n)) so space complexity is O(n). We could reduce this down to O(1) if we didn’t convert the number to a string, but instead used the bits of the number to iterate through .
Please Login to comment...