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++ 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;
}
// 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
# 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
// 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
<script>
// JavaScript program for the above approach
let mod = 1e9 + 7;
// Function to calculate Nth term of
// general recurrence relations
function NthTerm(F, C, K, n)
{
// Stores the generated sequence
let ans = new Uint8Array(n + 1);
for (let i = 0; i < K; i++)
ans[i] = F[i];
for (let i = K; i <= n; i++) {
for (let 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
document.write(ans[n] + "<br>");
}
// Driver Code
// Given Array F[] and C[]
let F = [ 0, 1 ];
let C = [ 1, 1 ];
// Given N and K
let K = 2;
let N = 10;
// Function Call
NthTerm(F, C, K, N);
// This code is contributed by Surbhi Tyagi.
</script>
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++ 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;
}
// 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
# 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
// 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
<script>
// Javascript program for the above approach
let mod = (1e9 + 7);
// Declare T[][] as global matrix
let T = new Array(2000);
// Result matrix
let result = new Array(2000);
for (let i = 0; i < 2000; i++)
{
T[i] = new Array(2000);
result[i] = new Array(2000);
for (let j = 0; j < 2000; j++)
{
T[i][j] = 0;
result[i][j] = 0;
}
}
// Function to multiply two matrices
function mul_2(K)
{
// Create an auxiliary matrix to
// store elements of the
// multiplication matrix
let temp = new Array(K + 1);
for (let i = 0; i <= K; i++)
{
temp[i] = new Array(K + 1);
for (let j = 0; j <= K; j++)
{
temp[i][j] = 0;
}
}
// Iterate over range [0, K]
for (let i = 1; i <= K; i++)
{
for (let j = 1; j <= K; j++)
{
for (let 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 (let i = 1; i <= K; i++)
{
for (let j = 1; j <= K; j++)
{
T[i][j] = temp[i][j];
}
}
}
// Function to multiply two matrices
function mul_1(K)
{
// Create an auxiliary matrix to
// store elements of the
// multiplication matrix
let temp = new Array(K + 1);
for (let i = 0; i <= K; i++)
{
temp[i] = new Array(K + 1);
for (let j = 0; j <= K; j++)
{
temp[i][j] = 0;
}
}
// Iterate over range [0, K]
for (let i = 1; i <= K; i++)
{
for (let j = 1; j <= K; j++)
{
for (let 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 (let i = 1; i <= K; i++)
{
for (let j = 1; j <= K; j++)
{
result[i][j] = temp[i][j];
}
}
}
// Function to calculate matrix^n
// using binary exponentaion
function matrix_pow(K, n)
{
// Initialize result matrix
// and unity matrix
for (let i = 1; i <= K; i++)
{
for (let 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 = parseInt(n / 2, 10);
}
}
// Function to calculate nth term
// of general recurrence
function NthTerm(F, C, K, n)
{
// Fill T[][] with appropriate value
for (let i = 1; i <= K; i++)
T[i][K] = C[K - i];
for (let i = 1; i <= K; i++)
T[i + 1][i] = 1;
// Function Call to calculate T^n
matrix_pow(K, n);
let answer = 0;
// Calculate nth term as first
// element of F * (T ^ n)
for (let i = 1; i <= K; i++)
{
answer += F[i - 1] * result[i][1];
}
// Print the result
document.write(answer + "</br>");
return 0;
}
// Given Initial terms
let F = [1, 2, 3];
// Given coefficients
let C = [1, 1, 1];
// Given K
let K = 3;
// Given N
let N = 10;
// Function Call
NthTerm(F, C, K, N);
// This code is contributed by mukesh07.
</script>
Output:
423
Time Complexity: O(K3log(N))
Auxiliary Space: O(K*K)