给定一个矩阵,求其前k次方的矩阵和。
二分+矩阵快速幂,S=(A1+A2+…+An)+(A1+A2+…+An)*k,然后递归求解A1+A2+…+An,递归结束条件k==1。
很早以前看的这题,当时不会,拖啊拖的,今天灵光乍现,不过A的也不顺利,递归一直写错,最后才AC。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef struct D {
int A[35][35];
}D;
D dd,kk;
int n,m;
D multi(D a,D b){
D t;
memset(t.A,0,sizeof(t.A));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
for(int k=0;k<n;k++){
t.A[i][j]+=a.A[i][k]*b.A[k][j];
t.A[i][j]%=m;
}
}
}
return t;
}
D add(D a,D b){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
a.A[i][j]+=b.A[i][j];
a.A[i][j]%=m;
}
}
return a;
}
D pow(int k){
D p=dd,ans;
memset(ans.A,0,sizeof(ans.A));
for(int i=0;i<n;i++){
ans.A[i][i]=1;
}
while(k>0){
if(k&1){
ans=multi(ans,p);
}
p=multi(p,p);
k>>=1;
}
return ans;
}
D calcu(int k){
if(k==1) return dd;
D t=calcu(k>>1);
if(k&1){
D tt=pow((k>>1)+1);
return add(add(t,tt),multi(t,tt));
}
else {
D tt=pow(k>>1);
return add(t,multi(t,tt));
}
}
int main(){
//freopen("in.txt","r",stdin);
int k;
cin>>n>>k>>m;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>dd.A[i][j];
kk.A[i][j]=dd.A[i][j];
}
}
D ss=calcu(k);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
printf("%d%s",ss.A[i][j],(j+1>=n)?"\n":" ");
}
}
return 0;
}
注:
不过题目的数据有点弱,有一个数据有明显的错误,这个代码还是AC了。此处注明,日后再解。
数据:
10 10000 100000
2 1 1 1 1 1 1 1 1 1
1 4 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 9 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1