矩阵系列定义如下:
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.
给定N和K ,找出系列的第 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 值增加得非常快,第 45个Fibonacci 数接近 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 现场工作专业课程和学生竞争性编程现场课程。