传送门
题意
给定矩阵$A_{n\times n}$,求$A^k$。
$k\leq 10^{12}, n\leq 100$
题解
这不是$\mathcal O(n^3 \lg k)$的矩阵乘法$+$快速幂板子吗。。
这里讲一下矩阵乘法规则:
$$A\times B={\begin{bmatrix} c_{1,1}&c_{1,2}&\cdots&c_{1,n}\\c_{2,1}&c_{2,2}&\cdots&c_{2,n}\\\vdots&\vdots&\cdots&\vdots\\c_{n,1}&c_{n,2}&\cdots&c_{n,n}\end{bmatrix}}$$
其中
$$c_{i,j}=\sum_{k=1}^n A_{i,k}\times B_{k,j} $$
然后嘛。矩阵乘法满足结合律。设$k$偶数,得
$$\begin{aligned}A^k&=A\times A\times\cdots\times A\\&=\left(A^{\frac{k}{2}}\right)\times\left(A^{\frac{k}{2}}\right)\end{aligned}$$
所以。可以用快速幂做啦!
贴代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef array<array<ll, 105>, 105> Matrix;
const ll P = 1000000007;
ll n, k;
Matrix A, I;
Matrix MatrixMul(const Matrix &A, const Matrix &B) {
Matrix ret;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++) {
ret[i][j] = 0;
for (int k=1; k<=n; k++)
(ret[i][j] += A[i][k] * B[k][j] % P) %= P;
}
return ret;
}
Matrix PowerMod(ll k) {
if (k == 0) return I;
if (k == 1) return A;
if (k & 1) return MatrixMul(PowerMod(k-1), A);
Matrix B = PowerMod(k >> 1);
return MatrixMul(B, B);
}
signed main() {
scanf("%lld%lld", &n,&k);
for (int i=1; i<=n; i++) {
for (int j=1; j<=n; j++) scanf("%lld", &A[i][j]);
I[i][i] = 1;
}
Matrix ret = PowerMod(k);
for (int i=1; i<=n; i++) {
for (int j=1; j<=n; j++) printf("%lld ", ret[i][j]);
puts("");
}
return 0;
}