线性代数——矩阵
作者:互联网
1. 定义
由 \(m × n\) 个数 \(a_{ij}\) 排成的 \(m\) 行 \(n\) 列的数表称为 \(m\) 行 \(n\) 列的矩阵,简称 \(m × n\) 矩阵。记作:
这 \(m×n\) 个数称为矩阵 \(A\) 的元素,简称为元,数 \(a_{ij}\) 位于矩阵 \(A\) 的第 \(i\) 行第 \(j\) 列,称为矩阵 \(A\) 的 \((i,j)\) 元,以数 \(a_{ij}\) 为 \((i,j)\) 元的矩阵可记为 \((a_{ij})\) 或 \((a_{ij})m × n\),\(m×n\) 矩阵 \(A\) 也记作 \(A_{mn}\)。
元素是实数的矩阵称为实矩阵,元素是复数的矩阵称为复矩阵。而行数与列数都等于 \(n\) 的矩阵称为 \(n\) 阶矩阵或 \(n\) 阶方阵
2.1.1 矩阵加减法
所谓矩阵其实就是一个数阵,我们可以把它看作一个二维数组。
这是矩阵的概念。
为了方便后面的学习,我们将一个矩阵记作大写字母,如 \(A,B,C\) 等等,而类比于二维数组,把矩阵中的每个数都用一个“坐标”来表示,记作:\(A(a,b)\) 等等。
这里引用高中数学必修四中平面向量中我认为很搞笑的一句话:如果没有运算,向量只是一个“路标”,因为有了运算,向量的力量无限。
好的,把这句话搬过来:如果没有运算,矩阵只是个数阵,因为有了运算,矩阵的力量无限。(话说数学中无限力量的有好多东西啊!)
那么在这里隆重介绍矩阵加减法的概念:
就是把对应位置的两个数相加减。
觉得太草率?
那来一波数学一点的定义:
对于两个矩阵 \(A,B\) 进行加减运算,得到的结果矩阵 \(C\) 具备以下性质:
\[C(a,b)=A(a,b)\pm B(a,b) \]需要说一下的是,进行矩阵加减法的两个矩阵必须尺寸相等。
你可能会说:这算什么啊,矩阵加减法还不能是大小不等的矩阵进行运算?
是的,就是不可以,这是规矩。后面的矩阵乘法的规矩还会更复杂。
2.1.2 矩阵乘法
矩阵乘法的定义比较复杂,建议这个地方画图理解,千万别懒,要不然会耽误很长时间,而且还可能造成理解不透彻。
为了证明它的确很复杂,就先上一波纯数学定义:
设 \(A\) 是 \(n*m\) 的矩阵,\(B\) 是 \(m*p\) 的矩阵,那么 \(C=A\times B\) 是一个 \(n\times p\) 的矩阵,其中每个数满足:
\[C(i,j)=\sum^{k=m}_{k=1}{A(i,k)\times B(k,j)} \]当然,我坚定不移地认为还是有人一看到这个式子就明白了矩阵乘法在干嘛。但是反正蒟蒻我数学比较菜,我用一种比较通俗的解释来定义矩阵乘法。
我的解释就是:一行乘一列,再相加。
比如你现在要得出结果矩阵 \(C\) 中的 \((3,5)\) 这个数,你就把 \(A\) 矩阵的第 \(3\) 行和 \(B\) 矩阵的第 \(5\) 列(你会发现这一行和这一列含有相同个数),然后把这些数依次相乘,最后再把这些乘积加到一起即可。
这就是矩阵乘法的概念了。
通过刚刚对矩阵乘法的定义中,我们应该能得出矩阵乘法运算的规矩:即 \(A\) 矩阵的列数和 \(B\) 矩阵的行数必须相等。比如 \(3\times 4\) 和 \(4\times 5\) 的矩阵可以相乘,但是 \(3\times 4\) 和 \(5\times 4\) 则不可以。
所以我们发现矩阵乘法的运算律:满足分配律和结合律,但是不满足交换律,因为交换后的矩阵并不能保证还符合定义中的“规矩”。
2.1.3 矩阵乘法加速递推
上文的讲解已经完成了对矩阵乘法概念的介绍,属于数学内容。其实,矩阵乘法是线性代数中很重要的一个模型,可以用来解决很多问题,事实上,它是和向量、线性方程组结合在一起的。有很多我们想不到的妙用。由于与信竞关系不大,便不予过多讲解。有兴趣的读者可以自己上网查阅相关资料。
那么接下来便开始介绍矩阵乘法在算法竞赛中的应用:加速递推。
我们用一道经典题目来认识矩阵乘法加速递推的过程:
求斐波那契数列的第 \(n\) 项。
斐波那契其实是最基本的递推问题,其递推式基本成为常识:\(f(n)=f(n-1)+f(n-2)\)。现在我们要求第 \(n\) 项的斐波那契数列,按照这个递推式,可以给出一个 \(O(n)\) 的解决方法。这个算法足以解决 \(10^7\) 以内的数据,并且支持取模。但是,假如要求的大一点,求 \(10^{12}\) 的数据呢?
我们顿时抓头了:\(O(n)\) 的已经很快了,再快一点...
矩乘就可以做到这一点。
我们来分析:为什么 \(O(n)\) 的算法还是不够快?就是因为,我们在算 \(f(n)\) 的时候,必须先把 \(f(n-1)\) 和 \(f(n-2)\) 算出来。但是题目只需要我们给出第n项,并不需要我们算出 \(1-n\) 项,所以我们在求 \(1-n-1\) 这些项的时候耗费了大量没必要的时间。
那么我们怎么才能把中间的递推过程简化呢?
设有矩阵 \(F(n)\) 是一个 \(1\times 2\) 的矩阵,\(F(n)=[fib_n\,\,\,\,fib_{n+1}]\) 。我们希望通过 \(F(n-1)\) 求出 \(F(n)\),那么这个 \(F(n)\) 矩阵的第一项就是要求的答案。因为 \(F(n-1)=[fib_{n-1}\,\,\,fib_{n}]\),那么,我们只需要把
这个矩阵的后一个数变成前一个数,并且把这两个数加和变成后一个数。(因为 \(fib_{n+1}=fib_{n}+fib_{n-1}\) )
那么,我们考虑在这个矩阵 \(F(n-1)\) 上乘以一个“状态矩阵”,实现这一目的。我们发现,这个矩阵是一个 \(2\times 2\) 的矩阵
每一次递推,我们只需要乘以这个状态矩阵即可,那么,只需要给出初值,即 \(fib_1,fib_2\) ,使之构成矩阵 \(F(1)\),设状态矩阵为 \(A\),我们只需要乘上 \(n-1\) 个 \(A\),就能得出我们最终需要的 \(F(n)\),也就是说:
\(F(n)=F(1)\times A^{n-1}\)
这是个矩阵递推式,我们发现,\(A^{n-1}\) 可以用一个快速幂方便的解决。
矩阵乘法代码:
int a[maxn][maxn],b[maxn][maxn],c[maxn][maxn];
void multiset(int a[][],int b[][],int n)
{
for(int i=1;i<=n;i++)
for(int k=1;k<=n;k++)
for(int j=1;j<=n;j++)
c[i][j]+=a[i][k]*b[k][j];
}
矩阵快速幂代码
int ret[maxn][maxn];
void qpow(int a[][],int n)
{
memset(ret,1,sizeof(ret));
while(n)
{
if(n&1)
multiset(ret,a,maxn);
multiset(a,a,maxn);
n>>=1;
}
}
这样我们就实现了矩阵乘法优化递推,这样算法的时间复杂度是 \(O(n^3logT)\)
3.高斯消元
高斯消元法是求解线性方阵组的一种算法,它也可用来求矩阵的秩,以及求可逆方阵的逆矩阵。它通过逐步消除未知数来将原始线性系统转化为另一个更简单的等价的系统。它的实质是通过初等行变化,将线性方程组的增广矩阵转化为行阶梯矩阵。
高斯消元法其实就是非常简单的过程
原线性方程组 \(\large \rightarrow\) 高斯消元法 $\large \rightarrow $下三角或上三角形式的线性方程组 \(\large \rightarrow\) 前向替换算法求解(对于上三角形式,采用后向替换算法).
标签:矩阵,times,fib,线性代数,maxn,递推,乘法 来源: https://www.cnblogs.com/spaceswalker/p/16512020.html