Power of Matrix
思路
书上的原题, 早就会了
听了一下 \(\rm{WGC}\) 大佬讲题, 这篇权当记录一下, 并且熟练一下矩阵 \(\LaTeX\) 的写法
首先我们发现, 直接往上加是慢的, 我们考虑先转化一下
令 \(s_i = A^0 + A^1 + A^2 + \cdots A^i\)
那么有, \(s_i = s_{i - 1} + A^i\)
考虑用这个来矩阵优化
容易想到设计矩阵
\[\begin{pmatrix}
s_i \\
A^i
\end{pmatrix}
\]
那么如何转移
显然的
\[\begin{pmatrix}
s_i \\
A^i
\end{pmatrix}
\cdot
\begin{pmatrix}
I & I \\
0 & A
\end{pmatrix}
=
\begin{pmatrix}
s_{i + 1} \\
A^{i + 1}
\end{pmatrix}
\]
直接做就好了
不是哥们, 思路错了
实际上我们需要把矩阵扔进去, 而非直接用矩阵套矩阵来处理
实现
框架
以这个题, 确定我矩阵的基本模板
实现
#include <bits/stdc++.h>
#define int long long
const int MAXN = 300;
const int MOD = 10;
int N, K, i, j;
struct Matrix
{
int M[MAXN][MAXN];
void clear() { memset(M, 0, sizeof(M)); }
void reset() {
clear();
for (int i = 1; i <= N; ++i)
M[i][i] = 1;
}
Matrix friend operator * (const Matrix &A, const Matrix &B) {
Matrix Ans;
Ans.clear();
for (int i = 1; i <= N; ++i)
for (int k = 1; k <= N; ++k)
for (int j = 1; j <= N; ++j)
Ans.M[i][j] = (Ans.M[i][j] + A.M[i][k] * B.M[k][j]) % MOD;
return Ans;
}
Matrix friend operator + (const Matrix &A, const Matrix &B) {
Matrix Ans;
Ans.clear();
for (int i = 1; i <= N; ++i)
for (int j = 1; j <= N; ++j)
Ans.M[i][j] = (A.M[i][j] + B.M[i][j]) % MOD;
return Ans;
}
} base, ans;
inline Matrix matrix_quickpow(Matrix T, int P)
{
Matrix Ans;
Ans.reset();
while (P)
{
if (P & 1)
Ans = Ans * T;
T = T * T;
P >>= 1;
}
return Ans;
}
signed main()
{
while (scanf("%lld %lld", &N, &K) && N && K)
{
base.clear(), ans.clear();
for (i = 1; i <= N; ++i) {
for (j = 1; j <= N; ++j)
scanf("%lld", &base.M[i][j]);
base.M[N + i][i] = base.M[N + i][N + i] = 1;
}
N <<= 1;
ans = matrix_quickpow(base, K + 1);
N >>= 1;
for (i = 1; i <= N; ++i)
for (j = 1; j <= N; ++j) {
int Out = ans.M[N + i][j] % MOD;
if (i == j)
Out = (Out + MOD - 1) % MOD;
printf("%lld", Out);
if (j == N) printf("\n");
else printf(" ");
}
printf("\n");
}
return 0;
}
总结
善于推导递推
矩阵的的特殊实现, 仅仅只需要把东西扔进去

浙公网安备 33010602011771号