题意:给出一个n*n 的矩阵A和一个正整数k,请你计算S=A+A^2+A^3+…+A^k。
把矩阵定义成结构体,可以套矩阵乘法与加法模板,用矩阵快速幂求解。求和时先用分治二分幂,记得要返回解出的和S时要判断幂的奇偶,若是偶数S=(A+A^2+A^3+…+A^k/2)+(A+A^2+A^3+…+A^k/2)* A^k/2 ,若是奇数S=(A+A^2+A^3+…+A^k/2)+(A+A^2+A^3+…+A^k/2)*A^k/2+A^k。
#include<stdio.h>
#include<string.h>
int n,k,mod;
struct mat
{
long long v[33][33]; //因为计算矩阵乘法结果时会超int范围,所以此处定义为long long
int n,m;
mat()
{
memset(v,0,sizeof(v));
n=m=0;
}
friend mat operator* (mat a,mat b) //矩阵乘法
{
mat c;
c.m=a.m,c.n=b.n;
for(int i=1;i<=c.m;i++)
for(int j=1;j<=c.n;j++)
for(int k=1;k<=a.n;k++)
{
c.v[i][j]=(c.v[i][j]+a.v[i][k]*b.v[k][j])%mod;
}
return c;
}
friend mat operator+ (mat a,mat b) //矩阵加法
{
mat c;
c.m=a.m,c.n=b.n;
for(int i=1;i<=c.m;i++)
for(int j=1;j<=c.n;j++)
{
c.v[i][j]=(a.v[i][j]+b.v[i][j])%mod;
}
return c;
}
};
mat a;
mat qkpow(mat a,int k)
{
mat c;
c.m=a.m,c.n=a.n;
for(int i=1;i<=c.m;i++)
{
c.v[i][i]=1;
}
mat t=a;
while(k>0)
{
if(k&1) c=c*t;
k>>=1;
t=t*t;
}
return c;
}
mat solve(mat a,long long k)
{
if(k==1) return a;
mat t1=solve(a,k>>1);
mat t2=qkpow(a,k>>1);
if(k&1) return t1+t2*t1+qkpow(a,k);
else return t1+t2*t1;
}
int main()
{
//freopen("1.txt","r",stdin);
//freopen("2.txt","w",stdout);
scanf("%d%d%d",&n,&k,&mod);
a.m=a.n=n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&a.v[i][j]);
}
mat ans=a;
ans=solve(a,k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",ans.v[i][j]);
}
printf("\n");
}
return 0;
}