题意:给定n*n的矩阵和一个整数k , 要求计算 S = A + A^2 + A^2 + ... + A^k。
思路:A^i 可以通过 矩阵快速幂求得,但是由于k比较大,普通矩阵累加和会TLE,这里学习了一种二分的方法。思路通过群里大牛的提示 + 参考了依然题解。
S = A + A^2 + ... + A^k/2 + A^k/2(A + A^2 + ... + A^k/2) 此时要讨论k的奇偶性,例如 k = 6 和 k = 7 的两种情况。
(i) k = 6 时
A + A^2 + A^3 + A^4 + A^5 + A^6 = A + A^2 + A^3 + A^3(A + A^2 + A^3)
(ii)k = 7 时
A + A^2 + A^3 + A^4 + A^5 + A^6 + A^7 = (A + A^2 + A^3) + A^4 + A^4(A + A^2 + A^3)
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int MAX = 30;
struct Matrax {
int m[MAX][MAX];
};
Matrax per , A;
int n , M;
Matrax Add(Matrax a , Matrax b) { // A + B
Matrax c;
int i , j;
for(i = 0 ; i < n ; i ++)
for (j = 0 ; j < n ; j ++) {
c.m[i][j] = 0;
c.m[i][j] = a.m[i][j] + b.m[i][j];
c.m[i][j]%=M;
}
return c;
}
Matrax multi(Matrax a , Matrax b) { // A * B
Matrax c;
int i , j , k;
for(i = 0 ; i < n ; i ++)
for(j = 0 ; j < n ; j ++) {
c.m[i][j] = 0;
for(k = 0 ; k < n ; k ++) {
c.m[i][j] += a.m[i][k]*b.m[k][j];
c.m[i][j]%=M;
}
}
return c;
}
Matrax power(int k) { // A^k
Matrax p , ans;
p = A;
ans = per;
while(k) {
if(k&1) {
ans = multi(ans , p);
k --;
}
k/=2;
p = multi(p , p);
}
return ans;
}
Matrax Matraxsum(int k) { //矩阵求和(二分)
if (k == 1) return A;
Matrax temp , b;
temp = Matraxsum(k/2);
if(k%2==0) {
b = power(k/2);
temp =Add(temp , multi(temp , b));
} else {
b = power(k/2+1);
temp = Add(temp , multi(temp , b));
temp = Add(temp , b);
}
return temp;
}
int main() {
int i , j , g , k;
Matrax S , temp;
scanf("%d%d%d",&n,&k,&M);
for(i = 0 ; i < n ; i ++)
for(j = 0 ; j < n ; j ++) {
scanf("%d",&A.m[i][j]);
per.m[i][j] = (i == j);
S.m[i][j] = 0;
}
S = Matraxsum(k);
for(i = 0 ; i < n ; i ++) {
for(j = 0 ; j < n ; j ++) {
if(j==(n-1)) printf("%d\n",S.m[i][j]);
else printf("%d ",S.m[i][j]);
}
}
//system("pause");
}