题意:
给一个矩阵A,让求A + A^2 + A^3 + A^4 + … + A^n
n (n ≤ 30), k (k ≤ 10^9) ,m (m < 10^4)
思路:
首先,将矩阵转化成递推的,
Sn-1 = a^1 + a^2 + a ^ 3 + …+a^n-1;
Sn = a^1 + a^2 + a ^ 3 + …+a^n-1 + a^n;
=>Sn = a^1 * Sn-1 + a^1
大佬的图,,嘤嘤嘤!!!
当然这就是一个分块矩阵,分块矩阵的乘法跟普通的差不多哈!!
接下来就是矩阵快速幂了
代码实现:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
int n,k ,mm;
struct node{
int m[100][100];
};
node res,tmp,G;
node mul(node a,node b){
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
tmp.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++){
tmp.m[i][j]=(tmp.m[i][j]+((a.m[i][k]*b.m[k][j])%mm))%mm;
}
}
}
return tmp;
}
node qpow(node a,int b){
node x;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
if(i == j) x.m[i][j] = 1;
else x.m[i][j] = 0;
}
}
while(b){
if(b & 1) x = mul(x,a);
b >>= 1;
a = mul(a,a);
}
return x;
}
int main(){
while(~scanf("%d%d%d",&n,&k,&mm)){
memset(res.m,0,sizeof(res.m));
memset(G.m,0,sizeof(G.m));
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
scanf("%d",&res.m[i][j]);
res.m[i][j] %= mm;
G.m[i][j] = G.m[i][j + n] = res.m[i][j];
}
res.m[i + n][i] = res.m[n + i][n + i] = 1;
}
n = n << 1;
node ans = qpow(res,k - 1);
G = mul(G,ans);
n = n >> 1;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
printf("%d%c",G.m[i][j],j == n - 1?'\n':' ');
}
}
}
return 0;
}