矩陣快速冪
功能
快速計算矩陣的次方冪
思路
將快速冪算法中的乘法運算替換爲矩陣乘法。若將表示爲,則可以表示爲,其中表示的二進制從右往左第位數字。
時間複雜度
測試
POJ:3070
應用
可根據遞推公式快速求序列某項的值。如數列的遞推公式可視爲
$$
\left[
\begin{matrix}
a_n \
a_{n-1}
\end{matrix}
\right]
\left[
\begin{matrix}
1 & 1 \
1 & 0
\end{matrix}
\right]
\left[
\begin{matrix}
a_{n-1} \
a_{n-2}
\end{matrix}
\right]
$$
模板
typedef long long LL;
const int maxn = 100;
struct Mat {
LL m[maxn][maxn];
};
/**
* @param a: the matrix A
* @param b: the matrix B
* @return: A*B
*/
Mat mul(Mat a, Mat b, int n) {
Mat ans;
memset(ans.m, 0, sizeof(ans.m));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
for (int k = 1; k <= n; ++k) {
ans.m[i][j] += a.m[i][k] * b.m[k][j];
}
}
}
return ans;
}
/**
* @param a: the base matrix A
* @param b: the exponent of power
* @return: A^b
* @other: b >= 0
*/
Mat FPM(Mat a, int b, int n) {
Mat ans;
memset(ans.m, 0, sizeof(ans.m));
for (int i = 1; i <= n; ++i) {
ans.m[i][i] = 1;
}
while (b > 0) {
if (b & 1) ans = mul(ans, a);
a = mul(a, a);
b >>= 1;
}
return ans;
}
擴展
對於較大的數需要取模。
模板
#include <cstring>
typedef long long LL;
const int maxn = 100;
const int mod = 1e9+7; // the divisor of answer
struct Mat {
LL m[maxn][maxn];
};
/**
* @param a: the matrix A
* @param b: the matrix B
* @return: A*B
*/
Mat mul(Mat a, Mat b, int n) {
Mat ans;
memset(ans.m, 0, sizeof(ans.m));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
for (int k = 1; k <= n; ++k) {
ans.m[i][j] += a.m[i][k] * b.m[k][j];
ans.m[i][j] %= mod;
}
}
}
return ans;
}
/**
* @param a: the base matrix A
* @param b: the exponent of power
* @return: A^b
* @other: b >= 0
*/
Mat FPM(Mat a, int b, int n) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
a.m[i][j] %= mod;
}
}
Mat ans;
memset(ans.m, 0, sizeof(ans.m));
for (int i = 1; i <= n; ++i) {
ans.m[i][i] = 1;
}
while (b > 0) {
if (b & 1) ans = mul(ans, a);
a = mul(a, a);
b >>= 1;
}
return ans;
}