经典题,两次二分。不知道为什么N取的稍大一点时进入函数时会调用chkstk.asm,让我恶心了很久也不知道为啥,不过不影响结果。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=33;
int n,M,K;
struct Mat
{
int mat[N][N],n,m;
void init(int r,int c)
{
n=r;m=c;
}
void init_e()
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mat[i][j]=(i==j);
}
};
Mat Mul(Mat a,Mat b)
{
Mat ret;
ret.init(a.n,b.m);
memset(ret.mat,0,sizeof(ret.mat));
for(int i=0;i<a.n;i++)
for(int j=0;j<b.m;j++)
for(int k=0;k<b.n;k++)
{
ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
if(ret.mat[i][j]>=M) ret.mat[i][j]%=M;
}
return ret;
}
Mat Add(Mat a,Mat b)
{
for(int i=0;i<a.n;i++)
for(int j=0;j<a.m;j++)
a.mat[i][j]+=b.mat[i][j];
return a;
}
Mat exp(Mat a,int k)
{
Mat ret=a,tmp=a;
ret.init_e();
for( ;k;k>>=1)
{
if(k&1)
{
ret=Mul(ret,tmp);
}
tmp=Mul(tmp,tmp);
}
return ret;
}
Mat sum(Mat a,int k)
{
if(k==1) return a;
Mat e=a; e.init_e();
if(k%2)
{
Mat ret=exp(a,k/2+1);
return Add(Mul(Add(e,ret),sum(a,k/2)),ret);
}
else
return Mul(Add(e,exp(a,k/2)),sum(a,k/2));
}
int main()
{
freopen("test.txt","r",stdin);
Mat A;
scanf("%d%d%d",&n,&K,&M);
A.init(n,n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&A.mat[i][j]);
Mat ret=sum(A,K);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d ",ret.mat[i][j]%M);
printf("\n");
}
return 0;
}