题目大意:
已知一个 n * n 的矩阵 A,计算
,S 的值对 m 取模。
思路:
对于单个矩阵的幂想到采用矩阵快速幂,但直接就和的话还是会有很多重复计算,可以分奇偶讨论k,对S二分:即k为偶数时,,其中
是子问题;k为奇数时,
,由此可实现二分求解,重复利用子问题的解。
AC代码:
#include<cstdio>
#include<iostream>
#define _CRT_SECURE_NO_WARNING
using std::cin;
typedef struct {
int m[31][31];
}mat;
mat A;
int mod;
mat mul(mat a, mat b, int n) {
mat c;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
c.m[i][j] = 0;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
c.m[i][k] = (c.m[i][k] + (a.m[i][j] * b.m[j][k]) % mod) % mod;
}
}
}
return c;
}
mat add(mat a, mat b, int n) {
mat c;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
c.m[i][j] = (a.m[i][j] + b.m[i][j])%mod;
}
}
return c;
}
mat pow(mat a, int n, int m) {
mat res;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) res.m[i][j] = 1;
else res.m[i][j] = 0;
}
}
int y = m;
mat x = a;
while (y) {
if (y % 2) {
res = mul(x, res, n);
}
x = mul(x, x, n);
y = y / 2;
}
return res;
}
mat binary_solve(int k, mat a, int n) {
if (k == 1) return a;
mat tmp = binary_solve(k / 2, a, n);
if (k % 2 == 1) {
mat y = pow(a, n, k / 2 + 1);
tmp = add(mul(y, tmp, n), tmp, n);
return add(tmp, y, n);
}
else {
mat y = pow(a, n, k / 2);
return add(mul(y, tmp, n), tmp, n);
}
}
void Print(mat a, int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%d ", a.m[i][j]);
}
printf("\n");
}
}
int main() {
int n, k;
cin >> n >> k >> mod;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> A.m[i][j];
A.m[i][j] = A.m[i][j] % mod;
}
}
Print(binary_solve(k, A, n), n);
return 0;
}