对于矩阵运算这块,由于最近遇到的题目比较多,所以有必要总结一下。有关矩阵基本运算的规则在这里就不详细说明了,一般线性代数的书上都有完整的叙述,在这里我们主要关心的是该如何实现它们,以及如何利用它们去求解相关题目。
一般来说,涉及矩阵的基础运算有加、乘、转置、逆等,还有一些基础的特殊矩阵也是我们应该注意的,如单位矩阵、零矩阵等,它们都是我们进行复杂运算的基础,所以在这篇文章中,我们将讨论其具体的实现。
由于时间问题,目前先讨论矩阵加法和乘法吧,其它的后面再补充吧。首先说说矩阵本身的表示,其实在代码层面上来说,矩阵其实就是一个二维数组,代表着矩阵有多少行、多少列,其次我们当我们真正写代码时,会将矩阵表示成结构体的形式,据说这样比较快。这样一来,运算就可以进行了,加法就是简单的将两个矩阵的对应位置元素相加,乘法的规则稍微复杂些,我们一般采用O(n^3)的算法,需要注意的是由于矩阵乘法不满足交换率,所以我们可以在运算过程中不断取模,避免高精度。下面直接给出基础矩阵运算的模版:
const int MAXN = 15;
const int MOD = 9973;
struct Mat
{
int n, m;
int mat[MAXN][MAXN];
Mat()
{
memset(mat, 0, sizeof(mat));
n = m = MAXN;
};
Mat operator * (Mat b) // 重载乘法
{
Mat c;
c = Mat();
c.n = n;
c.m = b.m;
for(int i=1; i<=n; ++i) // 注意这里从1开始
for(int j=1; j<=b.m; ++j)
{
//if(mat[j][i] <= 0) continue; // 剪枝
for(int k=1; k<=m; ++k)
{
//if(b.mat[i][k] <= 0) continue; // 剪枝
c.mat[i][j] += (mat[i][k]*b.mat[k][j]) % MOD;
c.mat[i][j] %= MOD;
}
}
return c;
}
Mat operator + (Mat b) // 重载加法
{
Mat c;
c.n = n;
c.m = m;
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)
c.mat[i][j] = mat[i][j] + b.mat[i][j];
return c;
}
void in(int x, int y) // 输入矩阵
{
n = x;
m = y;
for(int i=1; i<=x; ++i)
for(int j=1; j<=y; ++j)
scanf("%d", &mat[i][j]);
}
void out() // 输出矩阵
{
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=m; ++j)
printf("%d ", mat[i][j]);
puts("");
}
}
};
接下来的文章我们继续讨论有关矩阵的运算,不过是稍微复杂的幂次运算,即快速幂算法,传送门( 点击打开链接)。