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:

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

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

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

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:

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

 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] 

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

Below is the implementation of the above approach:
 

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

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

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

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.




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.



Article Tags :
Practice Tags :