Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.
Input
The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.
Output
Output the elements of S modulo m in the same way as A is given.
Sample Input
2 2 4
0 1
1 1
Sample Output
1 2
2 3
题意:已知一个n*n的矩阵A,和一个正整数k,求S = A + A2 + A3 + … + Ak。
思路:矩阵快速幂。首先我们知道 A^x 可以用矩阵快速幂求出来(具体可见poj 3070)。其次可以对k进行二分,每次将规模减半,分k为奇偶两种情况,如当k = 6和k = 7时有:
k = 10 有: S(9) = ( A^1+A^2+A^3+A^4+ A^5 ) + A^5 * ( A^1+A^2+A^3+A^4+A^5 ) = S(5) + A^5 * S(5)
k = 5 有: S(5) = ( A^1+A^2 ) + A^3 + A^3 * ( A^1+A^2 ) = S(2) + A^3 + A^3 * S(2)
k = 2 有 : S(2) = A^1 + A^2 = S(1) + A^1 * S(1)
从上面几个式子可以发现,当k为奇数或者偶数的区别,具体见代码中的solve函数。(solve函数的功能:递推到底层,也就是到 k = 1时回退,最后一步一步求出,弄懂递推的思想,这题也就明白了),当然定义成数组,然后再进行一些预处理,效率会更高些。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,mod;
struct matrix{
int arr[40][40];
};
matrix unit,init;
matrix mul(matrix a,matrix b){
matrix c;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
c.arr[i][j]=0;
for(int k=0;k<n;k++)
c.arr[i][j]=(c.arr[i][j]+a.arr[i][k]*b.arr[k][j]%mod)%mod;
c.arr[i][j]%=mod;
}
}
return c;
}
matrix pow(matrix a,matrix b,int x){
while(x){
if(x&1){
b=mul(b,a);
}
a=mul(a,a);
x>>=1;
}
return b;
}
matrix add(matrix a,matrix b){
matrix c;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
c.arr[i][j]=(a.arr[i][j]+b.arr[i][j])%mod;
}
}
return c;
}
matrix solve(int x){
if(x==1)
return init;
matrix res=solve(x/2),cur;
if(x&1){
cur=pow(init,unit,x/2+1);
res=add(res,mul(cur,res));
res=add(res,cur);
}
else{
cur=pow(init,unit,x/2);
res=add(res,mul(cur,res));
}
return res;
}
int main()
{
scanf("%d%d%d",&n,&k,&mod);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%d",&init.arr[i][j]);
unit.arr[i][j]=(i==j?1:0);
}
}
matrix res=solve(k);
for(int i=0;i<n;i++){
for(int j=0;j<n-1;j++)
printf("%d ",res.arr[i][j]);
printf("%d\n",res.arr[i][n-1]);
}
return 0;
}