Nth term of a recurrence relation generated by two given arrays

Given an integer N and two arrays F[] and C[] of size K that represent the first K terms and coefficient of first K terms of the below recurrence relation respectively.

FN = C1*FN – 1 + C2*FN – 2 + C3*FN – 3 +….+ CK*FN – K.

The task is to find the Nth term of the recurrence relation. Since the number can be very large take modulo to 109 + 7.
Examples:

Input: N = 10, K = 2, F[] = {0, 1}, C[] = {1, 1} 
Output: 55 
Explanation: 
FN= FN – 1 + FN – 2 with F0 = 0, F1 = 1 
The above recurrence relation forms the Fibonacci sequence with two initial values. 
The remaining terms of the series can be calculated as the sum of previous K terms with corresponding multiplication with coefficient stored in C[]
Therefore, F10 = 55.

Input: N = 5, K = 3, F[] = {1, 2, 3}, C[] = {1, 1, 1} 
Output: 20 
Explanation: 
The sequence of the above recurrence relation is 1, 2, 3, 6, 11, 20, 37, 68, …. 
Every next term is the sum of the previous (K = 3) terms with base condition F0 = 1, F1 = 2 and F2 = 3 
Therefore, F5 = 20.



Naive Approach: The idea is to generate the sequence using the given recurrence relation by calculating each term with the help of the previous K terms. Print the Nth Term after the sequence is formed.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
int mod = 1e9 + 7;
 
// Function to calculate Nth term of
// general recurrence relations
void NthTerm(int F[], int C[], int K,
             int n)
{
    // Stores the generated sequence
    int ans[n + 1] = { 0 };
 
    for (int i = 0; i < K; i++)
        ans[i] = F[i];
 
    for (int i = K; i <= n; i++) {
 
        for (int j = i - K; j < i; j++) {
 
            // Current term is sum of
            // previous k terms
            ans[i] += ans[j];
            ans[i] %= mod;
        }
    }
 
    // Print the nth term
    cout << ans[n] << endl;
}
 
// Driver Code
int main()
{
    // Given Array F[] and C[]
    int F[] = { 0, 1 };
    int C[] = { 1, 1 };
 
    // Given N and K
    int K = 2;
    int N = 10;
 
    // Function Call
    NthTerm(F, C, K, N);
 
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for the above approach
import java.util.*;
import java.lang.*;
 
class GFG{
     
static double mod = 1e9 + 7;
 
// Function to calculate Nth term of
// general recurrence relations
static void NthTerm(int F[], int C[], int K,
                    int n)
{
     
    // Stores the generated sequence
    int ans[] = new int[n + 1 ];
 
    for(int i = 0; i < K; i++)
        ans[i] = F[i];
 
    for(int i = K; i <= n; i++)
    {
        for(int j = i - K; j < i; j++)
        {
             
            // Current term is sum of
            // previous k terms
            ans[i] += ans[j];
            ans[i] %= mod;
        }
    }
 
    // Print the nth term
    System.out.println(ans[n]);
}
 
// Driver Code
public static void main (String[] args)
{
     
    // Given Array F[] and C[]
    int F[] = { 0, 1 };
    int C[] = { 1, 1 };
 
    // Given N and K
    int K = 2;
    int N = 10;
 
    // Function call
    NthTerm(F, C, K, N);
}
}
 
// This code is contributed by jana_sayantan

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach
mod = 1e9 + 7
 
# Function to calculate Nth term of
# general recurrence relations
def NthTerm(F, C, K, n):
 
    # Stores the generated sequence
    ans = [0] * (n + 1)
     
    i = 0
    while i < K:
        ans[i] = F[i]
        i += 1
 
    i = K
    while i <= n:
        j = i - K
        while j < i:
             
            # Current term is sum of
            # previous k terms
            ans[i] += ans[j]
            ans[i] %= mod
            j += 1
             
        i += 1
 
    # Print the nth term
    print(int(ans[n]))
     
# Driver code
if __name__ == '__main__':
 
    # Given Array F[] and C[]
    F = [ 0, 1 ]
    C = [ 1, 1 ]
 
    # Given N and K
    K = 2
    N = 10
 
    # Function call
    NthTerm(F, C, K, N)
 
# This code is contributed by jana_sayantan

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for
// the above approach
using System;
class GFG{
     
static double mod = 1e9 + 7;
 
// Function to calculate Nth term of
// general recurrence relations
static void NthTerm(int [] F, int [] C,
                    int K, int n)
{
  // Stores the generated sequence
  int []ans = new int[n + 1];
 
  for(int i = 0; i < K; i++)
    ans[i] = F[i];
 
  for(int i = K; i <= n; i++)
  {
    for(int j = i - K; j < i; j++)
    {
      // Current term is sum of
      // previous k terms
      ans[i] += ans[j];
      ans[i] %= (int)mod;
    }
  }
 
  // Print the nth term
  Console.WriteLine(ans[n]);
}
 
// Driver Code
public static void Main (String[] args)
{
  // Given Array F[] and C[]
  int [] F= {0, 1};
  int [] C= {1, 1};
 
  // Given N and K
  int K = 2;
  int N = 10;
 
  // Function call
  NthTerm(F, C, K, N);
}
}
 
// This code is contributed by jana_sayantan

chevron_right


Output: 

55








Time Complexity: O(N2
Auxiliary Space: O(N)

Efficient Approach: The Nth term of the recurrence relation can be found by using Matrix Exponentiation. Below are the steps:

  • Let’s consider the initial states as:

 F = [f0, f1, f2…………………………………fk-1]

  • Define a matrix of size K2 as:

 T = 
  [0, 0, 0, …………., Ck] 
  [1, 0, 0, …………., Ck-1] 
  [0, 1, 0, …………., Ck-2] 
  [………………………..] 
  [………………………..] 
  [0, 0, 0, …………, 0, C2] 
  [0, 0, 0, …………, 0, C2] 
  [0, 0, 0, …………, 1, C1] 

  • Calculate the Nth power of matrix T[][] using binary exponentiation.
  • Now, multiplying F[] with Nth power of T[][] gives:

 FxTN = [FN, FN + 1, FN + 2, …………………….., FN + K]

  • The first term of the resultant matrix F x TN is the required result.

Below is the implementation of the above approach:
 

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
int mod = 1e9 + 7;
 
// Declare T[][] as global matrix
int T[2000][2000];
 
// Result matrix
int result[2000][2000];
 
// Function to multiply two matrices
void mul_2(int K)
{
    // Create an auxiliary matrix to
    // store elements of the
    // multiplication matrix
    int temp[K + 1][K + 1];
    memset(temp, 0, sizeof temp);
 
    // Iterate over range [0, K]
    for (int i = 1; i <= K; i++) {
 
        for (int j = 1; j <= K; j++) {
 
            for (int k = 1; k <= K; k++) {
 
                // Update temp[i][j]
                temp[i][j]
                    = (temp[i][j]
                       + (T[i][k] * T[k][j])
                             % mod)
                      % mod;
            }
        }
    }
 
    // Update the final matrix
    for (int i = 1; i <= K; i++) {
        for (int j = 1; j <= K; j++) {
            T[i][j] = temp[i][j];
        }
    }
}
 
// Function to multiply two matrices
void mul_1(int K)
{
    // Create an auxiliary matrix to
    // store elements of the
    // multiplication matrix
    int temp[K + 1][K + 1];
    memset(temp, 0, sizeof temp);
 
    // Iterate over range [0, K]
    for (int i = 1; i <= K; i++) {
 
        for (int j = 1; j <= K; j++) {
 
            for (int k = 1; k <= K; k++) {
 
                // Update temp[i][j]
                temp[i][j]
                    = (temp[i][j]
                       + (result[i][k] * T[k][j])
                             % mod)
                      % mod;
            }
        }
    }
 
    // Update the final matrix
    for (int i = 1; i <= K; i++) {
        for (int j = 1; j <= K; j++) {
            result[i][j] = temp[i][j];
        }
    }
}
 
// Function to calculate matrix^n
// using binary exponentaion
void matrix_pow(int K, int n)
{
    // Initialize result matrix
    // and unity matrix
    for (int i = 1; i <= K; i++) {
        for (int j = 1; j <= K; j++) {
            if (i == j)
                result[i][j] = 1;
        }
    }
 
    while (n > 0) {
        if (n % 2 == 1)
            mul_1(K);
        mul_2(K);
        n /= 2;
    }
}
 
// Function to calculate nth term
// of general recurrence
int NthTerm(int F[], int C[], int K,
            int n)
{
 
    // Fill T[][] with appropriate value
    for (int i = 1; i <= K; i++)
        T[i][K] = C[K - i];
 
    for (int i = 1; i <= K; i++)
        T[i + 1][i] = 1;
 
    // Function Call to calculate T^n
    matrix_pow(K, n);
 
    int answer = 0;
 
    // Calculate nth term as first
    // element of F*(T^n)
    for (int i = 1; i <= K; i++) {
        answer += F[i - 1] * result[i][1];
    }
 
    // Print the result
    cout << answer << endl;
    return 0;
}
 
// Driver Code
int main()
{
    // Given Initial terms
    int F[] = { 1, 2, 3 };
 
    // Given coefficients
    int C[] = { 1, 1, 1 };
 
    // Given K
    int K = 3;
 
    // Given N
    int N = 10;
 
    // Function Call
    NthTerm(F, C, K, N);
 
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for
// the above approach
import java.util.*;
class GFG{
 
static int mod = (int) (1e9 + 7);
 
// Declare T[][] as global matrix
static int [][]T = new int[2000][2000];
 
// Result matrix
static int [][]result = new int[2000][2000];
 
// Function to multiply two matrices
static void mul_2(int K)
{
  // Create an auxiliary matrix to
  // store elements of the
  // multiplication matrix
  int [][]temp = new int[K + 1][K + 1];
 
  // Iterate over range [0, K]
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      for (int k = 1; k <= K; k++)
      {
        // Update temp[i][j]
        temp[i][j] = (temp[i][j] +
                     (T[i][k] * T[k][j]) %
                      mod) % mod;
      }
    }
  }
 
  // Update the final matrix
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      T[i][j] = temp[i][j];
    }
  }
}
 
// Function to multiply two matrices
static void mul_1(int K)
{
  // Create an auxiliary matrix to
  // store elements of the
  // multiplication matrix
  int [][]temp = new int[K + 1][K + 1];
 
  // Iterate over range [0, K]
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      for (int k = 1; k <= K; k++)
      {
        // Update temp[i][j]
        temp[i][j] = (temp[i][j] +
                     (result[i][k] * T[k][j]) %
                      mod) % mod;
      }
    }
  }
 
  // Update the final matrix
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      result[i][j] = temp[i][j];
    }
  }
}
 
// Function to calculate matrix^n
// using binary exponentaion
static void matrix_pow(int K, int n)
{
  // Initialize result matrix
  // and unity matrix
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      if (i == j)
        result[i][j] = 1;
    }
  }
 
  while (n > 0)
  {
    if (n % 2 == 1)
      mul_1(K);
    mul_2(K);
    n /= 2;
  }
}
 
// Function to calculate nth term
// of general recurrence
static int NthTerm(int F[], int C[],
                   int K, int n)
{
  // Fill T[][] with appropriate value
  for (int i = 1; i <= K; i++)
    T[i][K] = C[K - i];
 
  for (int i = 1; i <= K; i++)
    T[i + 1][i] = 1;
 
  // Function Call to calculate T^n
  matrix_pow(K, n);
 
  int answer = 0;
 
  // Calculate nth term as first
  // element of F * (T ^ n)
  for (int i = 1; i <= K; i++)
  {
    answer += F[i - 1] * result[i][1];
  }
 
  // Print the result
  System.out.print(answer + "\n");
  return 0;
}
 
// Driver Code
public static void main(String[] args)
{
  // Given Initial terms
  int F[] = {1, 2, 3};
 
  // Given coefficients
  int C[] = {1, 1, 1};
 
  // Given K
  int K = 3;
 
  // Given N
  int N = 10;
 
  // Function Call
  NthTerm(F, C, K, N);
}
}
 
// This code is contributed by 29AjayKumar

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for
# the above approach
mod = 1e9 + 7
 
# Declare T[][] as global matrix
T = [[0 for x in range (2000)]
        for y in range (2000)]
 
# Result matrix
result = [[0 for x in range (2000)]
             for y in range (2000)]
 
# Function to multiply two matrices
def mul_2(K):
 
    # Create an auxiliary matrix to
    # store elements of the
    # multiplication matrix
    temp = [[0 for x in range (K + 1)]
               for y in range (K + 1)]
  
    # Iterate over range [0, K]
    for i in range (1, K + 1):
        for j in range (1, K + 1):
            for k in range (1, K + 1):
 
                # Update temp[i][j]
                temp[i][j] = ((temp[i][j] +
                              (T[i][k] * T[k][j]) %
                               mod) % mod)
          
    # Update the final matrix
    for i in range (1, K + 1):
        for j in range (1, K + 1):
            T[i][j] = temp[i][j]
 
# Function to multiply two matrices
def mul_1(K):
 
    # Create an auxiliary matrix to
    # store elements of the
    # multiplication matrix
    temp = [[0 for x in range (K + 1)]
               for y in range (K + 1)]
     
    # Iterate over range [0, K]
    for i in range (1, K + 1):
        for j in range (1, K + 1):
            for k in range (1, K + 1):
 
                # Update temp[i][j]
                temp[i][j] = ((temp[i][j] +
                              (result[i][k] * T[k][j]) %
                               mod) % mod)
 
    # Update the final matrix
    for i in range (1, K + 1):
        for j in range (1, K + 1):
            result[i][j] = temp[i][j]
 
# Function to calculate matrix^n
# using binary exponentaion
def matrix_pow(K, n):
 
    # Initialize result matrix
    # and unity matrix
    for i in range (1, K + 1):
        for j in range (1, K + 1):
            if (i == j):
                result[i][j] = 1
        
    while (n > 0):
        if (n % 2 == 1):
            mul_1(K)
        mul_2(K)
        n //= 2
 
# Function to calculate nth term
# of general recurrence
def NthTerm(F, C, K, n):
 
    # Fill T[][] with appropriate value
    for i in range (1, K + 1):
        T[i][K] = C[K - i]
 
    for i in range (1, K + 1):
        T[i + 1][i] = 1
 
    # Function Call to calculate T^n
    matrix_pow(K, n)
 
    answer = 0
 
    # Calculate nth term as first
    # element of F*(T^n)
    for i in range (1, K + 1):
        answer += F[i - 1] * result[i][1]
    
    # Print the result
    print(int(answer))
 
# Driver Code
if __name__ == "__main__":
   
    # Given Initial terms
    F = [1, 2, 3]
 
    # Given coefficients
    C = [1, 1, 1]
 
    # Given K
    K = 3
 
    # Given N
    N = 10
 
    # Function Call
    NthTerm(F, C, K, N)
 
# This code is contributed by Chitranayal

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for
// the above approach
using System;
class GFG{
 
static int mod = (int) (1e9 + 7);
 
// Declare T[,] as global matrix
static int [,]T = new int[2000, 2000];
 
// Result matrix
static int [,]result = new int[2000, 2000];
 
// Function to multiply two matrices
static void mul_2(int K)
{
  // Create an auxiliary matrix to
  // store elements of the
  // multiplication matrix
  int [,]temp = new int[K + 1,
                        K + 1];
 
  // Iterate over range [0, K]
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      for (int k = 1; k <= K; k++)
      {
        // Update temp[i,j]
        temp[i, j] = (temp[i, j] +
                     (T[i, k] * T[k, j]) %
                      mod) % mod;
      }
    }
  }
 
  // Update the readonly matrix
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      T[i, j] = temp[i, j];
    }
  }
}
 
// Function to multiply two matrices
static void mul_1(int K)
{
  // Create an auxiliary matrix to
  // store elements of the
  // multiplication matrix
  int [,]temp = new int[K + 1,
                        K + 1];
 
  // Iterate over range [0, K]
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      for (int k = 1; k <= K; k++)
      {
        // Update temp[i,j]
        temp[i,j] = (temp[i, j] +
                    (result[i, k] * T[k, j]) %
                     mod) % mod;
      }
    }
  }
 
  // Update the readonly matrix
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      result[i, j] = temp[i, j];
    }
  }
}
 
// Function to calculate matrix^n
// using binary exponentaion
static void matrix_pow(int K, int n)
{
  // Initialize result matrix
  // and unity matrix
  for (int i = 1; i <= K; i++)
  {
    for (int j = 1; j <= K; j++)
    {
      if (i == j)
        result[i, j] = 1;
    }
  }
 
  while (n > 0)
  {
    if (n % 2 == 1)
      mul_1(K);
    mul_2(K);
    n /= 2;
  }
}
 
// Function to calculate nth term
// of general recurrence
static int NthTerm(int []F, int []C,
                   int K, int n)
{
  // Fill T[,] with appropriate value
  for (int i = 1; i <= K; i++)
    T[i, K] = C[K - i];
 
  for (int i = 1; i <= K; i++)
    T[i + 1, i] = 1;
 
  // Function Call to calculate T^n
  matrix_pow(K, n);
 
  int answer = 0;
 
  // Calculate nth term as first
  // element of F * (T ^ n)
  for (int i = 1; i <= K; i++)
  {
    answer += F[i - 1] * result[i, 1];
  }
 
  // Print the result
  Console.Write(answer + "\n");
  return 0;
}
 
// Driver Code
public static void Main(String[] args)
{
  // Given Initial terms
  int []F = {1, 2, 3};
 
  // Given coefficients
  int []C = {1, 1, 1};
 
  // Given K
  int K = 3;
 
  // Given N
  int N = 10;
 
  // Function Call
  NthTerm(F, C, K, N);
}
}
  
// This code is contributed by Rajput-Ji

chevron_right


Output: 

423








Time Complexity: O(K3log(N)) 
Auxiliary Space: O(K*K)

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.




My Personal Notes arrow_drop_up

Recommended Posts:


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.