YBTOJ 6.1例4 矩阵求和 题解
暴力怎么写很显然
暴力过不去也很显然
这题的关键在于矩阵套矩阵 那么我们构造一个矩阵 使ta的某一个元素为 \(\sum\limits_{i=1}^kA^i\) 即可
那么我们思考一下怎么构造
首先在此矩阵里构造一个 A 的 x + 1 次项是非常简单的
然后这个时候假如我们的矩阵里还有 \(\sum\limits_{i=1}^xA^i\) 那我们就能转移出下一个矩阵的对应
并且在下一项中应该还有 A 的 x + 2 次项在对应位置
那么我们可以猜这个项是由 A 的 x + 1 次项乘 A 加上一个什么项乘 0 得到的
同理 sum 项由原来的 sum 项乘 I 加上 A 的 x + 1 次项得到的
然后经过一顿蒙数学直觉的猜想 就可以构造出下面这个矩阵:
\(\begin{vmatrix}A&I\\0&I\end{vmatrix}\)
ta正好满足上述的所有性质
答案即为这个矩阵的 k + 1 次方的右上角元素减一个单位矩阵
code:
#include <bits/stdc++.h>
using namespace std;
const int N = 31;
int n, m, k;
struct Matrix {
int a[N][N];
};
struct node {
Matrix a[3][3];
};
void init_Matrix(Matrix &x) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (i == j) x.a[i][j] = 1;
else x.a[i][j] = 0;
}
}
}
void set_Matrix(Matrix &x) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) x.a[i][j] = 0;
}
}
Matrix operator * (Matrix x, Matrix y) {
Matrix ret;
set_Matrix(ret);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
for (int k = 1; k <= n; ++k) {
ret.a[i][j] += x.a[i][k] * y.a[k][j];
ret.a[i][j] %= m;
}
}
}
return ret;
}
Matrix operator + (Matrix x, Matrix y) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
x.a[i][j] = x.a[i][j] + y.a[i][j];
x.a[i][j] %= m;
}
}
return x;
}
void init_node(node &x) {
for (int i = 1; i <= 2; ++i) {
for (int j = 1; j <= 2; ++j) {
if (i == j) init_Matrix(x.a[i][j]);
else set_Matrix(x.a[i][j]);
}
}
}
void set_node(node &x) {
for (int i = 1; i <= 2; ++i) {
for (int j = 1; j <= 2; ++j) set_Matrix(x.a[i][j]);
}
}
node operator * (node x, node y) {
node ret;
set_node(ret);
for (int i = 1; i <= 2; ++i) {
for (int j = 1; j <= 2; ++j) {
for (int k = 1; k <= 2; ++k) {
Matrix tmp = x.a[i][k] * y.a[k][j];
ret.a[i][j] = ret.a[i][j] + tmp;
}
}
}
return ret;
}
void print(node x) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (i == j) printf("%d ",(x.a[1][2].a[i][j] - 1 + m) % m);
else printf("%d ",x.a[1][2].a[i][j]);
}
printf("\n");
}
}
node ksm_node(node x, int k) {
node ret;
init_node(ret);
while (k) {
if (k & 1) ret = ret * x;
x = x * x;
k >>= 1;
}
return ret;
}
int main() {
scanf("%d%d%d", &n, &k, &m);
node x;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) scanf("%d", &x.a[1][1].a[i][j]);
}
init_Matrix(x.a[1][2]);
init_Matrix(x.a[2][2]);
set_Matrix(x.a[2][1]);
x = ksm_node(x, k + 1);
print(x);
return 0;
}
(关于print函数里那个+m ybt上不加m才能AC 但是实际上你不加m连样例都过不去 std出大锅)

浙公网安备 33010602011771号