Fibonacci Power

Given a number n. You are required to find ( Fib(n) ^ Fib(n) ) % 10^9 + 7, where Fib(n) is the nth fibonacci number.

Examples :

Input : n = 4
Output : 27
4th fibonacci number is 3
[ fib(4) ^ fib(4) ] % 10^9 + 7 = ( 3 ^ 3 ) % 10^9 + 7 = 27

Input : n = 3
Output : 4
3th fibonacci number is 2
[ fib(3) ^ fib(3) ] % 10^9 + 7 = ( 2 ^ 2 ) % 10^9 + 7 = 4



If n is large, fib(n) will be huge and fib(n) ^ fib(n) is not only difficult to calculate but its storage is impossible.

Approach:
( a ^ (p-1) ) % p = 1 where p is prime number (using Fermat Little Theorem).
( a ^ a ) % m can be written as ( ( a % m ) ^ a ) % m
It is also possible to write any number ‘a’ as a = k * ( m – 1 ) + r (Using Division Algorithm)
where ‘k’ is quotient and ‘r’ is remainder. We can say that r = a % (m-1)
So, Steps to reduce our calculation, lets suppose a = fib(n)

  ( a ^ a ) % m 
= ( ( a % m ) ^ a ) % m 
= ( ( a % m ) ^ ( k * ( m - 1 ) + r ) ) % m 
= ( ( ( a % m ) ^ ( m-1 ) ) ^ k  * ( a % m ) ^ r ) % m
= ( (1 ^ k) * ( a % m ) ^ r ) % m
= ( ( a % m ) ^ r ) % m   
= ( ( a % m ) ^ (a % (m-1) ) % m 

a % m and a % (m-1) are easy to calculate and easy to store.
and we can calculate ( x ^ y ) % m using this GFG article.
We can find nth fibonacci number in log(n) time using this GFG article.

Below is the implementation of above approach :

filter_none

edit
close

play_arrow

link
brightness_4
code

#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
   
// Iterative function to compute modular power
long long modularexpo(long long x, long long y, long long p)
{
    // Initialize result
    long long res = 1; 
    // Update x if it is more than or
    // equal to p
    x = x % p; 
   
    while (y > 0) {
        // If y is odd, multiply x with result
        if (y & 1)
            res = (res * x) % p;
   
        // y must be even now
        y = y >> 1; 
        x = (x * x) % p;
    }
    return res;
}
  
// Helper function that multiplies 2 matrices
// F and M of size 2*2, and puts the
// multiplication result back to F[][]
void multiply(long long F[2][2], long long M[2][2], long long m)
{
    long long x = ((F[0][0] * M[0][0]) % m + 
                   (F[0][1] * M[1][0]) % m) % m;
  
    long long y = ((F[0][0] * M[0][1]) % m + 
                   (F[0][1] * M[1][1]) % m) % m;
  
    long long z = ((F[1][0] * M[0][0]) % m + 
                   (F[1][1] * M[1][0]) % m) % m;
  
    long long w = ((F[1][0] * M[0][1]) % m + 
                   (F[1][1] * M[1][1]) % m) % m;
   
    F[0][0] = x;
    F[0][1] = y;
    F[1][0] = z;
    F[1][1] = w;
}
  
// Helper function that calculates F[][] raise to 
// the power n and puts the  result in F[][] 
// Note that this function is designed only for fib() 
// and won't work as general power function 
void power(long long F[2][2], long long n, long long m)
{
    if (n == 0 || n == 1)
        return;
    long long M[2][2] = { { 1, 1 }, { 1, 0 } };
   
    power(F, n / 2, m);
    multiply(F, F, m);
   
    if (n % 2 != 0)
        multiply(F, M, m);
}
  
// Function that returns nth Fibonacci number 
long long fib(long long n, long long m)
{
    long long F[2][2] = { { 1, 1 }, { 1, 0 } };
    if (n == 0)
        return 0;
    power(F, n - 1, m);
    return F[0][0];
}
  
// Driver Code
int main()
{
    long long n = 4;
    long long base = fib(n, mod) % mod;
    long long expo = fib(n, mod - 1) % (mod - 1);
    long long result = modularexpo(base, expo, mod) % mod;
    cout << result << endl;
}

chevron_right


Output:

27

Time Complexity: log(n)



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.