这题关键就是矩阵的快速幂,和如何快速求和,这两点都是由二分法来实现的,求和的二分法就是把一段和看成前半段和后半段,求和就是求前半段的和,加上前半段的和乘以一个原数组的(k/2或k/2+1)次方,这样一直递归到1,再返回就可以求出解了。
#include <stdio.h>
#include <string.h>
struct node
{
int a[35][35];
node(){memset(a,0,sizeof(a));};
}plus,init;
int n,k,m;
node mul(node p1,node p2)
{
node p3;
int i,j,l;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
for(l=0;l<n;l++)
{
p3.a[i][j]=(p3.a[i][j]+p1.a[i][l]*p2.a[l][j])%m;
}
return p3;
}
node add(node p1,node p2)
{
node p3;
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
p3.a[i][j]=(p1.a[i][j]+p2.a[i][j])%m;
}
return p3;
}
node multi(int k1)
{
node init1=init,plus1=plus;
while(k1)
{
if(k1&1)
{
init1=mul(init1,plus1);
}
k1>>=1;
plus1=mul(plus1,plus1);
}
return init1;
}
node solve(int k)
{
if(k==1)
return plus;
if(k&1)
{
node tmp=solve(k/2);
node tmpk=multi(k/2+1);
return add(tmpk,add(tmp,mul(tmp,tmpk)));
}
else
{
node tmp=solve(k/2);
node tmpk=multi(k/2);
return add(tmp,mul(tmp,tmpk));
}
}
int main()
{
scanf("%d%d%d",&n,&k,&m);
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
scanf("%d",&plus.a[i][j]);
plus.a[i][j]=(plus.a[i][j])%m;
}
for(i=0;i<n;i++)
{
init.a[i][i]=1;
}
node ans=solve(k);
for(i=0;i<n;i++)
{
for(j=0;j<n-1;j++)
printf("%d ",ans.a[i][j]);
printf("%d\n",ans.a[i][j]);
}
return 0;
}