📜  Sudo展示位置2 |矩阵系列

📅  最后修改于: 2021-05-24 17:22:04             🧑  作者: Mango

Matrix系列定义如下:

给定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,2,3 … ..术语分别。 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) 

随着斐波那契值迅速增加,第45斐波那契数接近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