题目:
思路分析:
题目要求输入N阶矩阵,可以动态定义二维数组A[N][N]
来存储该矩阵A。由于矩阵A的M次幂也是N阶矩阵,那么需要定义另一个数组B[N][N]
来存储该矩阵。
在继续分析之前需要明确矩阵的乘法规则(举例如下图图1,不清楚者可自行百度,此处不再赘述)。由于矩阵A的0次幂是N阶单位矩阵,1次幂是其本身,所以本题难点是其M次幂(M≥2)的求解。
下面详细分析M次幂(M≥2)的求解:
以三阶矩阵,求其3次幂为例。A3 = A×A×A =B0×A×A=B1×A=B2,需要循环两次,每次利用B[N][N]
接收每次产生的结果。因此大循环是需要将矩阵B循环乘以A矩阵。当利用矩阵乘法规则计算时,我本想直接利用每次计算后的bij元素更新,类似bij=bij×aij。但是发现在计算下一个元素时还会用到bij,因此每次计算一个新元素都需要一个变量储存,共需要N×N个,由于N不固定,无法提前定义N×N个变量。所以想到再动态定义一个数组C[N][N]
来存储。
那么如何循环计算每个元素呢?
寻找规律:如图2,A3 = A×A×A =B0×A×A=B1×A=B2,要求出每个Bi,都要包括3层小循环,每次求出一个元素:下图2中三行之和为一个元素,即:[0 0]×[0 0]+[0 1]×[1 0]+[0 2]×[2 0],存入到C[0][0]中。这是一个小循环,又要分别求出行列3×3个元素,外套两层循环。
程序总体思路:
(半路出家,程序流程图不太会,见谅)
代码如下:
运行环境:Code::Blocks 20.20
#include <stdio.h>
int main(void)
{
int N, M, i, j, k = 0, l;
scanf("%d %d", &N, &M);
int A[N][N], B[N][N], C[N][N];
/*键入值A[N][N]矩阵*/
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
scanf("%d", &A[i][j]);
}
}
/*初始化B[N][N],方便后续计算*/
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
B[i][j] = A[i][j];
}
}
if(0 == M)
{
/*打印 M = 0 时的结果,注意:矩阵的0次幂是单位矩阵*/
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
if(i == j)
{
printf("1 ");
}else{
printf("0 ");
}
}
printf("\n");
}
}else if(1 == M){
/*打印 M = 1 时的结果*/
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
printf("%d ", B[i][j]);
}
printf("\n");
}
}else{
/*此处为重点:最里面的循环是求出矩阵乘积的一个元素,同时将其存入数组C[][]中,第二层和第三层
是求出N×N个元素,最外面求M次幂,即上文中提到的:A×A×A =B0×A×A=B1×A=B2,矩阵A的值是不改变的,
只有矩阵B的值改变,就是将C[][]中的元素赋值给B[][]中的过程*/
while(--M > 0)
{
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
l = 0;
for(k = 0; k < N; k++)
{
l = B[i][k]*A[k][j]+l;
}
C[i][j] = l;
}
}
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
B[i][j] = C[i][j];
}
}
}
/*打印 M >= 2 时的结果*/
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
printf("%d ", B[i][j]);
}
printf("\n");
}
}
return 0;
}