题目链接:
题目大意:
给一个
n×n
的矩阵
A
,再给一个
令
S=A+A2+⋯+Ak
,
输出
S
各元素对
数据范围:
1≤n≤301≤k≤1091≤M<104
解题思路:
哎!弱鸡,,,惊叹于大佬的构造,甚感矩阵之强大!
直接说方法吧!
令
E
为单位矩阵,
(AE0E)
同时,令:
Sk=E+A+A2+⋯+Ak−1
则有:
(AkSk) = (AE0E) (Ak−1Sk−1) = (AE0E)k (E0)
学艺不精,做的太丑了,,,自己都看不下去了,,,
由此,通过计算那个矩阵的 (k+1) 幂就可计算出 S 了。时间复杂度为
还需要注意的是,计算出的 Sk+1=E+A+A2+⋯+Ak ,最后还要减去一个单位矩阵 E <script type="math/tex" id="MathJax-Element-4832">E</script>。
可以当做一个板子存起来,代码:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf = 1 << 30;
const LL INF = 1LL << 60;
int n, mod, k;
struct Matrix {
int m[65][65];
};
Matrix operator * (Matrix a, Matrix b) { //矩阵乘法
Matrix c;
memset(c.m, 0, sizeof(c.m));
for(int i = 1; i <= 2 * n; i++) {
for(int j = 1; j <= 2 * n; j++) {
for(int k = 1; k <= 2 * n; k++) {
c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]) % mod;
}
}
}
return c;
}
Matrix operator ^ (Matrix a, int y) { //矩阵快速幂
Matrix c;
for(int i = 1; i <= 2 * n; i++)
c.m[i][i] = 1;
while(y > 0) {
if(y & 1) c = c * a;
a = a * a;
y = y >> 1;
}
return c;
}
Matrix A;
void solve() {
Matrix B;
//构造矩阵
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
B.m[i][j] = A.m[i][j];
}
B.m[n + i][i] = 1;
B.m[n + i][n + i] = 1;
}
B = B ^ (k + 1); //E + A + A^2 + ... A^k
//最后减去一个单位矩阵E
for(int i = 1; i <= n; i++)
B.m[n + i][i] = (B.m[n + i][i] + mod - 1) % mod;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(j == n) printf("%d\n", B.m[n + i][j]);
else printf("%d ", B.m[n + i][j]);
}
}
}
int main()
{
while(scanf("%d %d %d", &n, &k, &mod) != EOF)
{
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
scanf("%d", &A.m[i][j]);
}
}
solve();
}
return 0;
}