题目:
Description
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
分析:
现有题解主要是两种做法 构造矩阵+矩阵快速幂 或者 二分加速
第二种方法不难理解,式子化简一下就可以了
第一种方法挑战中直接给了一个矩阵,并没有细讲怎么想到构造这个矩阵的
http://blog.csdn.net/wangjian8006/article/details/7868864 怎么想到用这个矩阵可以参考这篇博客
代码:
方法一代码参挑战
方法二:二分
/*
二分可过 等比数列和的二分加速
k为偶数:sum(k) = (1+A^(k/2)) *( A+A^2+……+A^(k/2)) = (1+A^(k/2)) * sum(k/2)
k为奇数:sum(k) = (1+A^(k/2)) * sum(k/2) + A^k
*/
#include<iostream>
#include<cstring>
#define size 35
using namespace std;
typedef long long ll;
int n,k,mod;
struct Mat{
int mat[size][size];
void clear(){
memset(mat,0,sizeof(mat));
}
Mat operator *(const Mat &e) const{
Mat tmp;
tmp.clear();
for(int k=0;k<size;k++)
for(int i=0;i<size;i++){
if(mat[i][k]==0) continue;
for(int j=0;j<size;j++){
if(e.mat[k][j]==0) continue;
tmp.mat[i][j]+=mat[i][k]*e.mat[k][j]%mod;
tmp.mat[i][j]%=mod;
}
}
return tmp;
}
Mat operator +(const Mat &e) const{
Mat tmp;
tmp.clear();
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
tmp.mat[i][j]=(mat[i][j]%mod+e.mat[i][j]%mod)%mod;
}
}
return tmp;
}
};
Mat m,E;
Mat pow(Mat ma,ll num){
Mat ans;
ans.clear();
for(int i=0;i<n;i++) ans.mat[i][i]=1;
while(num){
if(num&1) ans=ans*ma;
num/=2;
ma=ma*ma;
}
return ans;
}
Mat Sum(int x){
if(x==1) return m;
if(x&1) return Sum(x-1)+pow(m,x);
else return (pow(m,x/2)+E)*Sum(x/2);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>k>>mod;
E.clear();
for(int i=0;i<n;i++){
E.mat[i][i]=1;
for(int j=0;j<n;j++) cin>>m.mat[i][j];
}
Mat ans=Sum(k);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
cout<<ans.mat[i][j]<<" ";
cout<<endl;
}
return 0;
}