Open In App

Sudo Placement 2 | Matrix Series

Improve
Improve
Like Article
Like
Save
Share
Report

A Matrix series is defined as follows:

M, MT, M(MT), M(MT)2, M2(MT)3, M3(MT)5, M5(MT)8 . . . . . . . ., where M is a binary square matrix of size K x K (Binary Matrix is a special type of Matrix where each element of the matrix is either 0 or 1) and MT represents the transpose of Matrix M.

Given N and K,  find the Nth term of the series.  Prerequisites : Modular Exponentiation Examples:

Input : N = 2, K = 4
        M = {
               {1, 1},
               {0, 1}
            }
Output : [ 3 1]
         [ 2 1]
Explanation:
The 4th term of the series is M2(MT)3 and the value of M2(MT)3  
is {{3, 1}, {2, 1}}.

Input : N = 2, K = 5
        M = {
              {1, 1},
              {0, 1}
        }
Output : [7 2]
         [3 1]
Explanation:
The 4th term of the series is M3(MT)5 and the value of M3(MT)5 
is {{7, 2}, {3, 1}}.

Approach : 

It can be observed that the powers of MT are 0, 1, 1, 2, 3, 5, 8….. for the 1st, 2nd, 3rd….. terms respectively. This pattern for the powers of MT is nothing but the Fibonacci series. Except for the first term, it can be seen that the powers of M also have the same pattern but, here the power of M is the same as the power of MT for the previous term. 

Since in Kth term MT has a power of fibK, M has the power of fibK – 1. Where fibi represents the ith fibonacci number. Thus, for the Kth term (for K ? 1) of the series can be calculated as:

Sk = Mfib(k - 1)(MT) fib(K) 

As Fibonacci values increase pretty fast the 45th Fibonacci number is close to 1010. So the Kth power cant be calculated by repeated multiplication of the matrices K times. To do this, efficiently we can calculate the Kth power of the matrix using an idea similar to Modular Exponentiation. 

As in Modular Exponentiation, the power is divided by 2 at every step, here also we follow the same Divide and conquer strategy except the fact that here we don’t multiply numbers, instead, here multiplication of matrices is required which can be done in O(N3), where N is the size of the square matrix. Below program illustrate the above approach: 

Implementation:

CPP




// CPP code to find Kth term of the Matrix Series
#include <bits/stdc++.h>
 
#define ll long long
#define mod 1000000007
 
using namespace std;
 
// This function multiplies two matrices A and B, under modulo mod
// and returns the resultant matrix after multiplication
vector<vector<int> > multiply(vector<vector<int> > A,
                            vector<vector<int> > B)
{
 
    // n is the size of the matrix
    int n = A.size();
 
    // Resultant matrix formed after multiplying matrix A and B
    vector<vector<int> > result(n, vector<int>(n, 0));
 
    // Matrix Multiplication
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                result[i][j] = (result[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
            }
        }
    }
 
    return result;
}
 
// Function to find the Kth power of matrix A of size nXn in O(logK)
// similar to Modular Exponentiation
vector<vector<int> > fastpower(vector<vector<int> > A, int n, ll K)
{
    // Base Case
    if (K == 1)
        return A;
 
    // Recursive Case1: If power is Odd
    if (K & 1) {
        // power(A, K) = power(A, K/2) * power(A, K/2) * A
        // when K is odd, Note than in this implementation
        // multiply (power(A, K - 1) * A) as in the case
        // the power becomes even in the next recursive call
        return multiply(A, fastpower(A, n, K - 1));
    }
 
    // power(A, K) = power(A, K/2) * power(A, K/2) if K is even
    vector<vector<int> > result = fastpower(A, n, K / 2);
    return multiply(result, result);
}
 
// Returns the transpose of the matrix A
vector<vector<int> > transpose(vector<vector<int> > A)
{
    int N = A.size();
    vector<vector<int> > transposeMatrix(N, vector<int>(N, 0));
 
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            transposeMatrix[i][j] = A[j][i];
        }
    }
 
    return transposeMatrix;
}
 
// Prints the matrix A
void printMatrix(vector<vector<int> > A)
{
    int n = A.size();
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << A[i][j] << " ";
        }
        cout << endl;
    }
}
 
// Return the Kth term of the series where matrix M
// is a boolean matrix of size n X n
void getKthTerm(vector<vector<int> > M, int n, int K)
{
 
    // precompue fibonacci till the Kth term
    ll fibonacci[K + 1];
 
    // ith fibonacci number denotes the power of M' in
    // the ith term, M' represents the transpose of M
    // 1st term has power of M' as 0 thus fib[0] = 1
    fibonacci[1] = 0ll;
    fibonacci[2] = 1ll;
    for (int i = 3; i <= K; i++) {
        fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
    }
 
    // stores the transpose of Matrix M
    vector<vector<int> > transposeM = transpose(M);
 
    // K = 1 and K = 2, is handled separately
    if (K == 1) {
        printMatrix(M);
    }
    else if (K == 2) {
        printMatrix(transposeM);
    }
 
    else {
        vector<vector<int> > MpowerFibKminusOne;
        MpowerFibKminusOne = fastpower(M, n, fibonacci[K - 1]);
 
        vector<vector<int> > MTransposePowerFibK;
        MTransposePowerFibK = fastpower(transposeM, n, fibonacci[K]);
 
        // kthTerm = (M^fib[K - 1]) * (transposeM ^ fib[K])
        vector<vector<int> > kthTerm = multiply(MpowerFibKminusOne,
                                                MTransposePowerFibK);
 
        // Print the Resultant Matrix
        printMatrix(kthTerm);
    }
}
 
// Driver Code
int main()
{
 
    int n, K;
    n = 2;
    K = 4;
    vector<vector<int> > M{ { 1, 1 }, { 0, 1 } };
    getKthTerm(M, n, K);
 
    // prints the 5th term
    K = 5;
    getKthTerm(M, n, K);
 
    return 0;
}


Java




// Java code to find Kth term of the Matrix Series
import java.util.*;
 
public class GFG {
 
  static int mod = 1000000007;
   
  // This function multiplies two matrices A and B, under
  // modulo mod and returns the resultant matrix after
  // multiplication
  static int[][] multiply(int[][] A, int[][] B)
  {
 
    // n is the size of the matrix
    int n = A.length;
 
    // Resultant matrix formded after multiplying matrix
    // A and B
    int[][] result = new int[n][n];
 
    // Matrix Multiplication
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        for (int k = 0; k < n; k++) {
          result[i][j]
            = (result[i][j]
               + (A[i][k] * B[k][j]) % mod)
            % mod;
        }
      }
    }
 
    return result;
  }
 
  // Function to find the Kth power of matrix A of size
  // nXn in O(logK) similar to Modular Exponentiation
  static int[][] fastpower(int[][] A, int n, long K)
  {
    // Base Case
    if (K == 1)
      return A;
 
    // Recursive Case1: If power is Odd
    if ((K & 1) != 0) {
      // power(A, K) = power(A, K/2) * power(A, K/2) *
      // A when K is odd, Note than in this
      // implementation multiply (power(A, K - 1) * A)
      // as in the case the power becomes even in the
      // next recursive call
      return multiply(A, fastpower(A, n, K - 1));
    }
 
    // power(A, K) = power(A, K/2) * power(A, K/2) if K
    // is even
    int[][] result = fastpower(A, n, K / 2);
    return multiply(result, result);
  }
 
  // Returns the transpose of the matrix A
  static int[][] transpose(int[][] A)
  {
    int N = A.length;
    int[][] transposeMatrix = new int[N][N];
 
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        transposeMatrix[i][j] = A[j][i];
      }
    }
 
    return transposeMatrix;
  }
 
  // Prints the matrix A
  static void printMatrix(int[][] A)
  {
    int n = A.length;
 
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        System.out.print(A[i][j] + " ");
      }
      System.out.println();
    }
  }
 
  // Return the Kth term of the series where matrix M
  // is a boolean matrix of size n X n
  static void getKthTerm(int[][] M, int n, int K)
  {
 
    // precompue fibonacci till the Kth term
    long[] fibonacci = new long[K + 1];
 
    // ith fibonacci number denotes the power of M' in
    // the ith term, M' represents the transpose of M
    // 1st term has power of M' as 0 thus fib[0] = 1
    fibonacci[1] = 0L;
    fibonacci[2] = 1L;
    for (int i = 3; i <= K; i++) {
      fibonacci[i]
        = fibonacci[i - 1] + fibonacci[i - 2];
    }
 
    // stores the transpose of Matrix M
    int[][] transposeM = transpose(M);
 
    // K = 1 and K = 2, is handled separately
    if (K == 1) {
      printMatrix(M);
    }
    else if (K == 2) {
      printMatrix(transposeM);
    }
 
    else {
      int[][] MpowerFibKminusOne;
      MpowerFibKminusOne
        = fastpower(M, n, fibonacci[K - 1]);
 
      int[][] MTransposePowerFibK;
      MTransposePowerFibK
        = fastpower(transposeM, n, fibonacci[K]);
 
      // kthTerm = (M^fib[K - 1]) * (transposeM ^
      // fib[K])
      int[][] kthTerm = multiply(MpowerFibKminusOne,
                                 MTransposePowerFibK);
 
      // Print the Resultant Matrix
      printMatrix(kthTerm);
    }
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int n, K;
    n = 2;
    K = 4;
    int[][] M = { { 1, 1 }, { 0, 1 } };
    getKthTerm(M, n, K);
 
    // prints the 5th term
    K = 5;
    getKthTerm(M, n, K);
  }
}
 
// This code is contributed by Karandeep1234


Python3




# Python3 code to find Kth term of the Matrix Series
mod = 1000000007;
 
# This function multiplies two matrices A and B, under modulo mod
# and returns the resultant matrix after multiplication
def multiply(A, B):
 
    # n is the size of the matrix
    n = len(A);
 
    # Resultant matrix formded after multiplying matrix A and B
    result = [[0] * n for _ in range(n)]
 
    # Matrix Multiplication
    for i in range(n):
        for j in range(n):
            for k in range(n):
                result[i][j] = (result[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
    return result;
 
# def to find the Kth power of matrix A of size nXn in O(logK)
# similar to Modular Exponentiation
def fastpower(A, n, K):
 
    # Base Case
    if (K == 1):
        return A;
 
    # Recursive Case1: If power is Odd
    if (K & 1 != 0) :
        # power(A, K) = power(A, K/2) * power(A, K/2) * A
        # when K is odd, Note than in this implementation
        # multiply (power(A, K - 1) * A) as in the case
        # the power becomes even in the next recursive call
        return multiply(A, fastpower(A, n, K - 1));
     
    # power(A, K) = power(A, K/2) * power(A, K/2) if K is even
    result = fastpower(A, n, int(K / 2));
    return multiply(result, result);
 
# Returns the transpose of the matrix A
def transpose(A):
 
    N = len(A);
    transposeMatrix =  [[0] * n for _ in range(n)]
 
    for i in range(N):
        for j in range(N):
            transposeMatrix[i][j] = A[j][i];
 
    return transposeMatrix;
 
# Prints the matrix A
def printMatrix(A):
 
    n = len(A);
 
    for i in range(n):
        print(*A[i])
     
# Return the Kth term of the series where matrix M
# is a boolean matrix of size n X n
def getKthTerm(M, n, K):
 
    # precompue fibonacci till the Kth term
    fibonacci = [0] * (K + 1)
 
    # ith fibonacci number denotes the power of M' in
    # the ith term, M' represents the transpose of M
    # 1st term has power of M' as 0 thus fib[0] = 1
    fibonacci[1] = 0;
    fibonacci[2] = 1;
    for i in range(3, 1 + K):
        fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
     
 
    # stores the transpose of Matrix M
    transposeM = transpose(M);
 
    # K = 1 and K = 2, is handled separately
    if (K == 1):
        printMatrix(M);
     
    elif (K == 2):
        printMatrix(transposeM);
     
    else :
        MpowerFibKminusOne = fastpower(M, n, fibonacci[K - 1]);
 
        MTransposePowerFibK = fastpower(transposeM, n, fibonacci[K]);
 
        # kthTerm = (M^fib[K - 1]) * (transposeM ^ fib[K])
        kthTerm = multiply(MpowerFibKminusOne, MTransposePowerFibK);
 
        # Print the Resultant Matrix
        printMatrix(kthTerm);
     
# Driver Code
n = 2;
K = 4;
M = [[1, 1 ], [0, 1]];
getKthTerm(M, n, K);
 
# prints the 5th term
K = 5;
getKthTerm(M, n, K);
 
# The code is contributed by phasing17


C#




// C# code to find Kth term of the Matrix Series
 
using System;
using System.Collections.Generic;
 
public class GFG {
 
  static int mod = 1000000007;
 
  // This function multiplies two matrices A and B, under
  // modulo mod and returns the resultant matrix after
  // multiplication
  static int[][] multiply(int[][] A, int[][] B)
  {
 
    // n is the size of the matrix
    int n = A.Length;
 
    // Resultant matrix formded after multiplying matrix
    // A and B
    int[][] result = new int[n][];
 
    // Matrix Multiplication
    for (int i = 0; i < n; i++) {
      result[i] = new int[n];
      for (int j = 0; j < n; j++) {
        for (int k = 0; k < n; k++) {
          result[i][j]
            = (result[i][j]
               + (A[i][k] * B[k][j]) % mod)
            % mod;
        }
      }
    }
 
    return result;
  }
 
  // Function to find the Kth power of matrix A of size
  // nXn in O(logK) similar to Modular Exponentiation
  static int[][] fastpower(int[][] A, int n, long K)
  {
    // Base Case
    if (K == 1)
      return A;
 
    // Recursive Case1: If power is Odd
    if ((K & 1) != 0) {
      // power(A, K) = power(A, K/2) * power(A, K/2) *
      // A when K is odd, Note than in this
      // implementation multiply (power(A, K - 1) * A)
      // as in the case the power becomes even in the
      // next recursive call
      return multiply(A, fastpower(A, n, K - 1));
    }
 
    // power(A, K) = power(A, K/2) * power(A, K/2) if K
    // is even
    int[][] result = fastpower(A, n, K / 2);
    return multiply(result, result);
  }
 
  // Returns the transpose of the matrix A
  static int[][] transpose(int[][] A)
  {
    int N = A.Length;
    int[][] transposeMatrix = new int[N][];
 
    for (int i = 0; i < N; i++) {
      transposeMatrix[i] = new int[N];
      for (int j = 0; j < N; j++) {
        transposeMatrix[i][j] = A[j][i];
      }
    }
 
    return transposeMatrix;
  }
 
  // Prints the matrix A
  static void printMatrix(int[][] A)
  {
    int n = A.Length;
 
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        Console.Write(A[i][j] + " ");
      }
      Console.WriteLine();
    }
  }
 
  // Return the Kth term of the series where matrix M
  // is a boolean matrix of size n X n
  static void getKthTerm(int[][] M, int n, int K)
  {
 
    // precompue fibonacci till the Kth term
    long[] fibonacci = new long[K + 1];
 
    // ith fibonacci number denotes the power of M' in
    // the ith term, M' represents the transpose of M
    // 1st term has power of M' as 0 thus fib[0] = 1
    fibonacci[1] = 0L;
    fibonacci[2] = 1L;
    for (int i = 3; i <= K; i++) {
      fibonacci[i]
        = fibonacci[i - 1] + fibonacci[i - 2];
    }
 
    // stores the transpose of Matrix M
    int[][] transposeM = transpose(M);
 
    // K = 1 and K = 2, is handled separately
    if (K == 1) {
      printMatrix(M);
    }
    else if (K == 2) {
      printMatrix(transposeM);
    }
 
    else {
      int[][] MpowerFibKminusOne;
      MpowerFibKminusOne
        = fastpower(M, n, fibonacci[K - 1]);
 
      int[][] MTransposePowerFibK;
      MTransposePowerFibK
        = fastpower(transposeM, n, fibonacci[K]);
 
      // kthTerm = (M^fib[K - 1]) * (transposeM ^
      // fib[K])
      int[][] kthTerm = multiply(MpowerFibKminusOne,
                                 MTransposePowerFibK);
 
      // Print the Resultant Matrix
      printMatrix(kthTerm);
    }
  }
 
  // Driver Code
  public static void Main(string[] args)
  {
    int n, K;
    n = 2;
    K = 4;
    int[][] M = { new int[] { 1, 1 }, new int[] { 0, 1 } };
    getKthTerm(M, n, K);
 
    // prints the 5th term
    K = 5;
    getKthTerm(M, n, K);
  }
}
 
// This code is contributed by phasing17


Javascript




// JavaScript code to find Kth term of the Matrix Series
let mod = 1000000007;
 
// This function multiplies two matrices A and B, under modulo mod
// and returns the resultant matrix after multiplication
function multiply(A, B)
{
 
    // n is the size of the matrix
    let n = A.length;
 
    // Resultant matrix formded after multiplying matrix A and B
    let result = new Array(n);
    for(let i = 0; i < n; i++){
        result[i] = new Array(n).fill(0);
    }
 
    // Matrix Multiplication
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            for (let k = 0; k < n; k++) {
                result[i][j] = (result[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
            }
        }
    }
 
    return result;
}
 
// Function to find the Kth power of matrix A of size nXn in O(logK)
// similar to Modular Exponentiation
function fastpower(A, n, K)
{
    // Base Case
    if (K == 1)
        return A;
 
    // Recursive Case1: If power is Odd
    if (K & 1 != 0) {
        // power(A, K) = power(A, K/2) * power(A, K/2) * A
        // when K is odd, Note than in this implementation
        // multiply (power(A, K - 1) * A) as in the case
        // the power becomes even in the next recursive call
        return multiply(A, fastpower(A, n, K - 1));
    }
 
    // power(A, K) = power(A, K/2) * power(A, K/2) if K is even
    let result = fastpower(A, n, Math.floor(K / 2));
    return multiply(result, result);
}
 
// Returns the transpose of the matrix A
function transpose(A)
{
    let N = A.length;
    let transposeMatrix = new Array(N);
    for(let i = 0; i < N; i++){
        transposeMatrix[i] = new Array(N).fill(0);
    }
 
    for (let i = 0; i < N; i++) {
        for (let j = 0; j < N; j++) {
            transposeMatrix[i][j] = A[j][i];
        }
    }
 
    return transposeMatrix;
}
 
// Prints the matrix A
function printMatrix(A)
{
    let n = A.length;
 
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            document.write(A[i][j] + " ");
        }
        document.write("\n");
    }
}
 
// Return the Kth term of the series where matrix M
// is a boolean matrix of size n X n
function getKthTerm(M, n, K)
{
 
    // precompue fibonacci till the Kth term
    let fibonacci = new Array(K+1).fill(0);
 
    // ith fibonacci number denotes the power of M' in
    // the ith term, M' represents the transpose of M
    // 1st term has power of M' as 0 thus fib[0] = 1
    fibonacci[1] = 0;
    fibonacci[2] = 1;
    for (let i = 3; i <= K; i++) {
        fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
    }
 
    // stores the transpose of Matrix M
    let transposeM = transpose(M);
 
    // K = 1 and K = 2, is handled separately
    if (K == 1) {
        printMatrix(M);
    }
    else if (K == 2) {
        printMatrix(transposeM);
    }
    else {
        let MpowerFibKminusOne;
        MpowerFibKminusOne = fastpower(M, n, fibonacci[K - 1]);
 
        let MTransposePowerFibK;
        MTransposePowerFibK = fastpower(transposeM, n, fibonacci[K]);
 
        // kthTerm = (M^fib[K - 1]) * (transposeM ^ fib[K])
        let kthTerm = multiply(MpowerFibKminusOne, MTransposePowerFibK);
 
        // Print the Resultant Matrix
        printMatrix(kthTerm);
    }
}
 
// Driver Code
let n, K;
n = 2;
K = 4;
let M = [[1, 1 ], [0, 1]];
getKthTerm(M, n, K);
 
// prints the 5th term
K = 5;
getKthTerm(M, n, K);
 
// The code is contributed by Gautam goel (gautamgoel962)


Output

3 1 
2 1 
7 2 
3 1 

Time Complexity: O(N3K), where N is the size of the square matrix, and K is the power to which it is raised.

Auxiliary Space: O(K), where K is the power to which the matrix is raised.



Last Updated : 25 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads