Matrix系列定义如下:
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,第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