📜  须藤安置2 |矩阵系列

📅  最后修改于: 2021-10-23 07:59:45             🧑  作者: Mango

矩阵系列定义如下:

给定NK ,找出系列的第 N 项。

先决条件:模幂运算

例子:

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}}.

方法 :
可以观察到, M T的幂分别为 0, 1, 1, 2, 3, 5, 8….. 对于 1 st , 2 nd , 3 rd ….. 项。这种 M T幂的模式只不过是斐波那契数列。

除了第一项,可以看出M的幂也有相同的模式,但是,这里 M 的幂与前一项的 M T 的幂相同。
由于在K 项中 M T具有 fib K的幂,因此 M 具有 fib K – 1的幂。
其中 fib i代表第 i斐波那契数。

因此,对于序列的第K 项(对于 K ≠ 1),可以计算为:

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

由于 Fibonacci 值增加得非常快,第 45Fibonacci 数接近 10 10 。所以K幂不能通过矩阵的重复相乘K次来计算。为此,我们可以使用类似于模幂的思想有效地计算矩阵的 K 次方。

就像在模幂中一样,幂在每一步都除以 2,这里我们也遵循相同的分治策略,只是这里我们不乘以数字,而是需要矩阵乘法,这可以在O(N 3 ),其中 N 是方阵的大小。

下面的程序说明了上述方法:

// CPP code to find Kth term of the Matrix Series
#include 
  
#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 > multiply(vector > A,
                              vector > B)
{
  
    // n is the size of the matrix
    int n = A.size();
  
    // Resultant matrix formded after multiplying matrix A and B
    vector > result(n, vector(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 > fastpower(vector > 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 > result = fastpower(A, n, K / 2);
    return multiply(result, result);
}
  
// Returns the transpose of the matrix A
vector > transpose(vector > A)
{
    int N = A.size();
    vector > transposeMatrix(N, vector(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 > 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 > 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 > transposeM = transpose(M);
  
    // K = 1 and K = 2, is handled separately
    if (K == 1) {
        printMatrix(M);
    }
    else if (K == 2) {
        printMatrix(transposeM);
    }
  
    else {
        vector > MpowerFibKminusOne;
        MpowerFibKminusOne = fastpower(M, n, fibonacci[K - 1]);
  
        vector > MTransposePowerFibK;
        MTransposePowerFibK = fastpower(transposeM, n, fibonacci[K]);
  
        // kthTerm = (M^fib[K - 1]) * (transposeM ^ fib[K])
        vector > kthTerm = multiply(MpowerFibKminusOne,
                                                MTransposePowerFibK);
  
        // Print the Resultant Matrix
        printMatrix(kthTerm);
    }
}
  
// Driver Code
int main()
{
  
    int n, K;
    n = 2;
    K = 4;
    vector > M{ { 1, 1 }, { 0, 1 } };
    getKthTerm(M, n, K);
  
    // prints the 5th term
    K = 5;
    getKthTerm(M, n, K);
  
    return 0;
}
 

输出 :

3 1 
2 1 
7 2 
3 1 

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。