题目链接:点我
题意:
给你一个矩阵 A, 让你求 A + A2 + A3 + A4 + A5 + …. An ,
思路:
矩阵倍增,那么怎么倍增呢, 令矩阵 S = A +
A2
+
A3
+
A4
+
A5
+ …
An
= A +
A2
+
A3
+
A4
+
A5
+
An/2
+
An/2
* ( A +
A2
+
A3
+
A4
+
A5
+ ….
An/2
)
于是,我们这样不断的重复下去,就能算出答案了.
代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int mod = 10;
int n,k;
struct mat{
int a[42][42];
mat(){memset(a, 0, sizeof(a)); }
mat operator *(const mat q){
mat c;
for(int i = 1; i <= n; ++i)
for(int k = 1; k <= n; ++k)
if(a[i][k])
for(int j = 1; j <= n; ++j){
c.a[i][j] += a[i][k] * q.a[k][j];
if(c.a[i][j] >= mod)
c.a[i][j] %= mod;
}return c;
}mat operator +(const mat q){
mat c;
for(int i = 1; i <= n;++i)
for(int j = 1; j <= n; ++j)
c.a[i][j] = (a[i][j] + q.a[i][j]) % mod;
return c;
}
};
mat qpow(mat x, int n){
mat ans;
for(int i = 1; i <= 40; ++i)
ans.a[i][i] = 1;
while(n){
if(n&1) ans =ans * x;
x = x * x;
n >>= 1;
}return ans;
}
mat solve(mat &x, int n){
if(n == 1) return x;
mat tmp = solve(x, n/2);
mat sum = tmp * qpow(x,n/2)+ tmp;
if(n&1) sum = sum + qpow(x,n);//如果n是奇数,那么我们应该加上一项.
return sum;
}
int main(){
while(scanf("%d %d", &n, &k) != EOF&&n){
mat ans;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n ;++j)
scanf("%d", &ans.a[i][j]),ans.a[i][j] %= 10;
ans = solve(ans, k);
for(int i = 1 ; i <= n ;++i){
for(int j = 1; j < n ;++j)
printf("%d ", ans.a[i][j]);
printf("%d\n",ans.a[i][n]);
}printf("\n");
}return 0;
}