第31届CSP认证游寄
特别声明:本文仅作本人成长过程的记录,无不良引导或其他特殊含义。
由于本文内容特殊,不接受任何形式的转载,感谢理解。
树总结
数据结构总结
2024/6/30 upd:填坑。
线代总结
线代总结
要是我不会 Ctrl+C Ctrl+V Ctrl+F 我的手就废了。
向量与矩阵
向量
有大小和方向的量被称为向量(Vector)。
在 OI 中,向量一般用一个水平或竖向放置的一维数组表示:
在这个例子中,
向量是线性代数的主要研究对象。
矩阵
发明这玩意的人一定是个天才吧。
一个
矩阵可以简单地理解为一个下标从
当
我们可以把一个矩阵看作
同形矩阵
两个矩阵
矩阵的加、减、数乘
两个矩阵能加减当且仅当这两个矩阵同形。
矩阵很大,你忍一下。
总之矩阵的加减就是矩阵对应位置加减,矩阵的数乘就是每个位置乘上这个数。
矩阵的转置
我们把矩阵的行列交换就是这个矩阵的转置,记作
矩阵乘法
两个矩阵能进行乘法当且仅当第一个矩阵的列数与第二个矩阵的行数相等。
(要是我再把整个矩阵都打出来我就要废了)
我们设
我们可以把
容易发现方阵可以无限地自乘,我们可以把方阵的自乘
单次矩乘的时间复杂度为
矩乘有结合律但是没有交换律,因此我们需要区分左乘与右乘。
卡常小寄巧
在实际写代码的时候按照 i,k,j
的顺序枚举变量,可以使内存访问连续,会稍微快一点。
1 | for(int i=1;i<=n;++i) |
矩乘的理解
由于写博客的蒟蒻都觉得这玩意比 LCT 还难理解,因此附上一种理解的方式。
我们首先行向量乘上列向量(即
也就是
现在我们把
此时
欸,是不是看出来点门道了?
我们进一步把
也就是
结合上文提到的把一个矩阵看作行向量或列向量的组合,我们把
我们试着画个图看一下(下图是一个
我们发现单独抽每一列出来,得到的答案都是
那么如果我把
而我们发现列向量在结果中也只会影响对应的这一列,因此我们找到了一个规律:两个矩阵相乘,结果的的第
事实上我们也可以先增加行向量的数量再增加列向量的数量,于是
矩阵的初等变换
我们定义下面的三种操作为矩阵的初等变换:
- 交换两行/列
- 把一行/列的倍数加到另一行/列上
- 把一行/列乘上一个常数
这三类初等变换都可以通过左乘或右乘一个矩阵来达成。
单位方阵
定义
也就是
单位方阵的性质:
在有了单位方阵后,我们就可以在这个单位方阵做手脚了。
下文只讨论行操作,因此只需要右乘。列操作换成左乘即可。
行交换
我们希望交换矩阵的第
行乘常数
我们希望把矩阵的第
行加另一行的倍数
我们希望把矩阵的第
证明直接带进去就好了。
矩阵快速幂
矩阵乘法有结合律,因此方阵自乘可以套用快速幂。
求
矩阵与递推
引入
求 Fibonacci 数列的第
我会递推!
hmmmmmmm...
这个问题可以用矩阵快速幂加速。
矩阵加速线性递推
Fibonacci 数列的递推式:
这是一个典型的线性递推,我们可以通过构造一个矩阵通过乘矩阵达到相同的效果。
首先
因为
因此
用矩阵快速幂加速即可,时间复杂度
类似的,如果我们要求下面这个递推式的第
我们同样设
我们构造出
满足条件。
这里还有一个例子:
你有一个
个结点的有向图,点 和点 之间有 条边,你需要求出从任意点出发走 步的方案数。两个方案不同当且仅当经过的点不同或经过的边不同。
。
我们很容易想出朴素 DP:定义
ちょっと待って,这个咋和矩阵乘法这么像?
我们把
这就是一个裸的矩阵乘法。
由于
时间复杂度
我们考虑 Floyd 也类似这个转移,所以 Floyd
实质上也是一种矩阵乘法(加法是
线性方程组与高斯消元
线性方程组
上式即为一个线性方程组的标准形式。
我们一般把
我们也可以写作增广矩阵,也就是在
比如下面这个线性方程组
就可以写作
或
高斯消元
我们可以用高斯消元来解线性方程组。
高斯消元的核心思想是把矩阵消成上三角阵,也就是主对角线以下都是
我们回忆一下小学解二元一次方程,大多都是通过其中一个式子乘上某个常数后减去另一个得到,现在我们试着把它推广到所有线性方程组。
现在假设要消去
我们随意地选取一行用它的倍数来减掉其他行里
由于每一次我们都会消掉一列,而消元完了后的行就没用了,只要重复这个过程,一定要么只剩一行要么只剩一列(不含增广的那一列)。
当
那么当这些
当
我们回到原问题,若方程有唯一解,那么我们就将这个解带到倒数第二个被消掉的方程里,然后就可以解出倒数第二个未知数;以此类推。
例子
我们假设要解方程
首先我们消掉第一列。
我们用第二行和第三行减去第一行:
此时
我们继续用第三行减去第二行:
再删掉第一行和第一列:
即
因此
我们把
即
解得
再把
解得
到此我们就解出了该方程的唯一一组解:
代码实现
代码实现上可能会有一些细微的差异。
令
- 找到第
列绝对值最大的元素。 - 如果找不到一个绝对值大于
的元素,说明这一列已经被消完了,令 并返回 1。 - 否则设我们找到绝对值最大的是第
行,将第 行与第 行交换。(优化精度) - 将第
行的所有元素除以 。 - 对第
行第 列的元素( ),将其减去 。 - 此时完成一轮消元,令
。
如果
否则方程有自由元,返回无穷多解。
如果方程有唯一解,那么我们从
在
1 | //Luogu3389 【模板】高斯消元法 |
高斯-约旦消元
回带还是太麻烦了,有没有什么不需要回带的方法吗?
有,高斯-约旦(Gauss-Jordan)消元就不需要回带。
和高斯消元消成上三角阵不同,Gauss-Jordan 消元的目标就是直接把矩阵消成对角阵。
Gauss-Jordan 消元与普通高斯消元的区别在于:Gauss-Jordan 消元不会缩小求解的范围。
它的大体流程如下:
- 选择一个主元。
- 选择一个含有该主元的方程。
- 用这个方程消去其他方程中的这个主元。
Gauss-Jordan 消元的优势在于码量较小、代码简单;缺点在于无法区分无解和无数解。
高斯消元的应用
求逆矩阵
如果
解法:构造一个增广矩阵
求行列式
定义一个方阵的行列式为
其中
行列式的性质:对矩阵作初等变换,行列式不变。
因此我们只需把矩阵消成上三角阵后,就只需要计算主对角线的乘积了(其他情况都必定有乘积结果为
出模数不是质数的出题人想必一定有点什么心理疾病吧。
Matrix-Tree 定理
设一张有向图
我们构造矩阵
那么如果我要求以
总结
OI 中线代内容不算多,但是在 DP 与数论等方面有一定意义,值得理解。