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++
#include <bits/stdc++.h>
using namespace std;
int mod = 1e9 + 7;
void NthTerm( int F[], int C[], int K,
int n)
{
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++) {
ans[i] += ans[j];
ans[i] %= mod;
}
}
cout << ans[n] << endl;
}
int main()
{
int F[] = { 0, 1 };
int C[] = { 1, 1 };
int K = 2;
int N = 10;
NthTerm(F, C, K, N);
return 0;
}
|
Java
import java.util.*;
import java.lang.*;
class GFG{
static double mod = 1e9 + 7 ;
static void NthTerm( int F[], int C[], int K,
int n)
{
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++)
{
ans[i] += ans[j];
ans[i] %= mod;
}
}
System.out.println(ans[n]);
}
public static void main (String[] args)
{
int F[] = { 0 , 1 };
int C[] = { 1 , 1 };
int K = 2 ;
int N = 10 ;
NthTerm(F, C, K, N);
}
}
|
Python3
mod = 1e9 + 7
def NthTerm(F, C, K, n):
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:
ans[i] + = ans[j]
ans[i] % = mod
j + = 1
i + = 1
print ( int (ans[n]))
if __name__ = = '__main__' :
F = [ 0 , 1 ]
C = [ 1 , 1 ]
K = 2
N = 10
NthTerm(F, C, K, N)
|
C#
using System;
class GFG{
static double mod = 1e9 + 7;
static void NthTerm( int [] F, int [] C,
int K, int n)
{
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++)
{
ans[i] += ans[j];
ans[i] %= ( int )mod;
}
}
Console.WriteLine(ans[n]);
}
public static void Main (String[] args)
{
int [] F= {0, 1};
int [] C= {1, 1};
int K = 2;
int N = 10;
NthTerm(F, C, K, N);
}
}
|
Javascript
<script>
let mod = 1e9 + 7;
function NthTerm(F, C, K, n)
{
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++) {
ans[i] += ans[j];
ans[i] %= mod;
}
}
document.write(ans[n] + "<br>" );
}
let F = [ 0, 1 ];
let C = [ 1, 1 ];
let K = 2;
let N = 10;
NthTerm(F, C, K, N);
</script>
|
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++
#include <bits/stdc++.h>
using namespace std;
int mod = 1e9 + 7;
int T[2000][2000];
int result[2000][2000];
void mul_2( int K)
{
int temp[K + 1][K + 1];
memset (temp, 0, sizeof temp);
for ( int i = 1; i <= K; i++) {
for ( int j = 1; j <= K; j++) {
for ( int k = 1; k <= K; k++) {
temp[i][j]
= (temp[i][j]
+ (T[i][k] * T[k][j])
% mod)
% mod;
}
}
}
for ( int i = 1; i <= K; i++) {
for ( int j = 1; j <= K; j++) {
T[i][j] = temp[i][j];
}
}
}
void mul_1( int K)
{
int temp[K + 1][K + 1];
memset (temp, 0, sizeof temp);
for ( int i = 1; i <= K; i++) {
for ( int j = 1; j <= K; j++) {
for ( int k = 1; k <= K; k++) {
temp[i][j]
= (temp[i][j]
+ (result[i][k] * T[k][j])
% mod)
% mod;
}
}
}
for ( int i = 1; i <= K; i++) {
for ( int j = 1; j <= K; j++) {
result[i][j] = temp[i][j];
}
}
}
void matrix_pow( int K, int n)
{
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;
}
}
int NthTerm( int F[], int C[], int K,
int n)
{
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;
matrix_pow(K, n);
int answer = 0;
for ( int i = 1; i <= K; i++) {
answer += F[i - 1] * result[i][1];
}
cout << answer << endl;
return 0;
}
int main()
{
int F[] = { 1, 2, 3 };
int C[] = { 1, 1, 1 };
int K = 3;
int N = 10;
NthTerm(F, C, K, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int mod = ( int ) (1e9 + 7 );
static int [][]T = new int [ 2000 ][ 2000 ];
static int [][]result = new int [ 2000 ][ 2000 ];
static void mul_2( int K)
{
int [][]temp = new int [K + 1 ][K + 1 ];
for ( int i = 1 ; i <= K; i++)
{
for ( int j = 1 ; j <= K; j++)
{
for ( int k = 1 ; k <= K; k++)
{
temp[i][j] = (temp[i][j] +
(T[i][k] * T[k][j]) %
mod) % mod;
}
}
}
for ( int i = 1 ; i <= K; i++)
{
for ( int j = 1 ; j <= K; j++)
{
T[i][j] = temp[i][j];
}
}
}
static void mul_1( int K)
{
int [][]temp = new int [K + 1 ][K + 1 ];
for ( int i = 1 ; i <= K; i++)
{
for ( int j = 1 ; j <= K; j++)
{
for ( int k = 1 ; k <= K; k++)
{
temp[i][j] = (temp[i][j] +
(result[i][k] * T[k][j]) %
mod) % mod;
}
}
}
for ( int i = 1 ; i <= K; i++)
{
for ( int j = 1 ; j <= K; j++)
{
result[i][j] = temp[i][j];
}
}
}
static void matrix_pow( int K, int n)
{
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 ;
}
}
static int NthTerm( int F[], int C[],
int K, int n)
{
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 ;
matrix_pow(K, n);
int answer = 0 ;
for ( int i = 1 ; i <= K; i++)
{
answer += F[i - 1 ] * result[i][ 1 ];
}
System.out.print(answer + "\n" );
return 0 ;
}
public static void main(String[] args)
{
int F[] = { 1 , 2 , 3 };
int C[] = { 1 , 1 , 1 };
int K = 3 ;
int N = 10 ;
NthTerm(F, C, K, N);
}
}
|
Python3
mod = 1e9 + 7
T = [[ 0 for x in range ( 2000 )]
for y in range ( 2000 )]
result = [[ 0 for x in range ( 2000 )]
for y in range ( 2000 )]
def mul_2(K):
temp = [[ 0 for x in range (K + 1 )]
for y in range (K + 1 )]
for i in range ( 1 , K + 1 ):
for j in range ( 1 , K + 1 ):
for k in range ( 1 , K + 1 ):
temp[i][j] = ((temp[i][j] +
(T[i][k] * T[k][j]) %
mod) % mod)
for i in range ( 1 , K + 1 ):
for j in range ( 1 , K + 1 ):
T[i][j] = temp[i][j]
def mul_1(K):
temp = [[ 0 for x in range (K + 1 )]
for y in range (K + 1 )]
for i in range ( 1 , K + 1 ):
for j in range ( 1 , K + 1 ):
for k in range ( 1 , K + 1 ):
temp[i][j] = ((temp[i][j] +
(result[i][k] * T[k][j]) %
mod) % mod)
for i in range ( 1 , K + 1 ):
for j in range ( 1 , K + 1 ):
result[i][j] = temp[i][j]
def matrix_pow(K, n):
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
def NthTerm(F, C, K, n):
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
matrix_pow(K, n)
answer = 0
for i in range ( 1 , K + 1 ):
answer + = F[i - 1 ] * result[i][ 1 ]
print ( int (answer))
if __name__ = = "__main__" :
F = [ 1 , 2 , 3 ]
C = [ 1 , 1 , 1 ]
K = 3
N = 10
NthTerm(F, C, K, N)
|
C#
using System;
class GFG{
static int mod = ( int ) (1e9 + 7);
static int [,]T = new int [2000, 2000];
static int [,]result = new int [2000, 2000];
static void mul_2( int K)
{
int [,]temp = new int [K + 1,
K + 1];
for ( int i = 1; i <= K; i++)
{
for ( int j = 1; j <= K; j++)
{
for ( int k = 1; k <= K; k++)
{
temp[i, j] = (temp[i, j] +
(T[i, k] * T[k, j]) %
mod) % mod;
}
}
}
for ( int i = 1; i <= K; i++)
{
for ( int j = 1; j <= K; j++)
{
T[i, j] = temp[i, j];
}
}
}
static void mul_1( int K)
{
int [,]temp = new int [K + 1,
K + 1];
for ( int i = 1; i <= K; i++)
{
for ( int j = 1; j <= K; j++)
{
for ( int k = 1; k <= K; k++)
{
temp[i,j] = (temp[i, j] +
(result[i, k] * T[k, j]) %
mod) % mod;
}
}
}
for ( int i = 1; i <= K; i++)
{
for ( int j = 1; j <= K; j++)
{
result[i, j] = temp[i, j];
}
}
}
static void matrix_pow( int K, int n)
{
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;
}
}
static int NthTerm( int []F, int []C,
int K, int n)
{
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;
matrix_pow(K, n);
int answer = 0;
for ( int i = 1; i <= K; i++)
{
answer += F[i - 1] * result[i, 1];
}
Console.Write(answer + "\n" );
return 0;
}
public static void Main(String[] args)
{
int []F = {1, 2, 3};
int []C = {1, 1, 1};
int K = 3;
int N = 10;
NthTerm(F, C, K, N);
}
}
|
Javascript
<script>
let mod = (1e9 + 7);
let T = new Array(2000);
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 mul_2(K)
{
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;
}
}
for (let i = 1; i <= K; i++)
{
for (let j = 1; j <= K; j++)
{
for (let k = 1; k <= K; k++)
{
temp[i][j] = (temp[i][j] +
(T[i][k] * T[k][j]) %
mod) % mod;
}
}
}
for (let i = 1; i <= K; i++)
{
for (let j = 1; j <= K; j++)
{
T[i][j] = temp[i][j];
}
}
}
function mul_1(K)
{
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;
}
}
for (let i = 1; i <= K; i++)
{
for (let j = 1; j <= K; j++)
{
for (let k = 1; k <= K; k++)
{
temp[i][j] = (temp[i][j] +
(result[i][k] * T[k][j]) %
mod) % mod;
}
}
}
for (let i = 1; i <= K; i++)
{
for (let j = 1; j <= K; j++)
{
result[i][j] = temp[i][j];
}
}
}
function matrix_pow(K, n)
{
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 NthTerm(F, C, K, n)
{
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;
matrix_pow(K, n);
let answer = 0;
for (let i = 1; i <= K; i++)
{
answer += F[i - 1] * result[i][1];
}
document.write(answer + "</br>" );
return 0;
}
let F = [1, 2, 3];
let C = [1, 1, 1];
let K = 3;
let N = 10;
NthTerm(F, C, K, N);
</script>
|
Time Complexity: O(K3log(N))
Auxiliary Space: O(K*K)
Last Updated :
14 Jun, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...