线性代数学习笔记
【定义】
-
向量:每个向量由若干个标量(数)组成,每个标量都来自同一个域 \(F\)。若一个向量包含 \(k\) 个标量,称其为 \(k\) 维向量。
-
向量空间 \(V\):由若干个向量组成。需要满足以下条件:
-
\(V\) 中的向量满足加法交换律和加法结合律。
-
\(V\) 中存在 \(0\) 向量,\(\vec{0}+\vec{u}=\vec{u}\)。
-
若 \(\vec{u}\in V\),则 \(-\vec{u}\in V\)。
-
记 \(a,b\) 为标量,\(a(b\vec{u})=(ab)\vec{u},(a+b)\vec{u}=a\vec{u}+b\vec{u}\)。
-
记 \(a\) 为标量,\(a(\vec{u}+\vec{v})=a\vec{u}+a\vec{v}\)。
-
-
线性表示:若有向量 \(\vec{v},\vec{a_1}\sim\vec{a_n}\),且存在一组标量 \((k_1\sim k_n)\) 使得 \(\vec{v}=\displaystyle\sum_{i=1}^nk_i\vec{a_i}\),则 \(\vec{v}\) 可被 \(\vec{a_1}\sim\vec{a_n}\) 线性表示。
-
线性相关:对于一个向量空间 \(V\) 内的 \(n\) 个向量 \((\vec{v_1},\vec{v_2},\dots,\vec{v_n})\),若存在一组标量 \((a_1,a_2,\dots,a_n)\) 满足 \(a_1\sim a_n\) 不全为 \(0\) 且 \(\displaystyle\sum_{i=1}^n a_i\vec{v_i}=\vec{0}\),则称 \(\vec{v_1}\sim \vec{v_n}\) 线性相关。
线性相关还有另外一个表述方式:\(\forall i\in [1,n]\cap\mathbb{Z},\vec{v_i}\) 不可被 \(\{\vec{v_1}\sim\vec{v_n}\}/\{\vec{v_i}\}\) 线性表示。
-
生成空间:对于一组向量 \(\vec{v_1}\sim\vec{v_n}\),定义其生成空间 \(V\):\(\forall (a_1,a_2,\dots,a_n)\neq (0,0,\dots,0)\),\((\sum a_i\vec{v_i})\in V\)。可以看出,\(V\) 是一个向量空间。
-
基:对于一个向量空间 \(V\),若能找出若干个向量,使它们的生成空间等于 \(V\),称这些向量为 \(V\) 的一组基。基可能不唯一。
定理:不论怎么找基,基中向量个数都等于 \(V\) 中向量的维度。
-
奇排列和偶排列:对于排列 \(p\),记其逆序对个数为 \(inv(p)\)。如果 \(inv(p)\) 为奇数,称为奇排列;否则称为偶排列。
-
矩阵的转置。对于一个 \(n\times m\) 的矩阵 \(E\),定义其转置矩阵 \(E^T\):\(E^T\) 为 \(m\times n\) 的矩阵,\(E^T_{i,j}=E_{j,i}\)。
【矩阵乘法】
【向量】
向量:一个有方向的量。
如果没有方向,称为 “标量”;有方向,就是 “向量”。
平面向量:就是 \(2\) 维向量。
维度:如果一个向量是 \(n\) 维的,说明它可以用 \(n\) 个数确定方向。
例如 \(2\) 维向量。
\(2\) 维向量,我们在 \(2\) 维平面上研究。因为我们不在乎起点和终点,所以我们可以把起点平移到原点。
此时,终点落在平面上的一个点 \((a_1,a_2)\) 上,这就是向量的坐标。
同理,在 \(3\) 维向量中,我们可以用 \((a_1,a_2,a_3)\) 来表示终点所在的坐标。
所以,维度就是表示我们用多少个数就可以确定平面上的点。
【矩阵的理解】
矩阵乘法,就是一个线性变换。
什么叫线性变换?
我们看一个函数:\(f(x)=kx\),这是一个一次函数,也就是线性的。
类推:\(f(x_1,x_2,\cdots,x_n)=\displaystyle \sum_{i=1}^n k_ix_i\),也是线性的。
这样我们通过 \((k_1,k_2,\cdots,k_n)\) 这个线性变换,把 \((x_1,x_2,\cdots,x_n)\) 变成了一个数。
观察矩阵乘法的运算法则:
\(c_{i,j}=\displaystyle \sum^k_{x=1}a_{i,x}\times b_{x,j}\),这不就是可以视为线性变换吗?
把 \(a_{i,x}\) 视作上面的 \(k_i\),\(b_{x,j}\) 视作上面的 \(x_i\),\(c_{i,j}\) 视作线性变换的结果。
再回过头看我们的矩阵乘法:
向量乘以矩阵,得出的向量就是经过线性变换后得出的向量。
两个矩阵相乘,既可以视作很多个向量存在矩阵里,依次进行线性变换;也可以视为得出一个先做第一个变换,再做第二个变换的等价变换。
【用矩阵处理问题】
我们说到,矩阵可以视作一个线性变换。
那么,如果我们的答案是一个经过若干次线性变换得出的,就可以考虑编成一个矩阵,然后利用快速幂在 \(\log\) 级别的时间内求出来。
例题:斐波那契数列,这题可谓相当经典。
我们看这个递推式:\(F_i=F_{i-2}+F_{i-1}\),满足 \(y=k_1x_1+k_2x_2\) 的形式,\(F_{i-2}\rightarrow x_1,F_{i-1}\rightarrow x_2\),这是线性变换!
所以我们可以考虑用矩阵乘法。
研究矩阵乘法的递推,我们从起点开始。
上面提到过,系数 \((k_1,\cdots,k_n)\) 是线性变换,那么 \(x_1,\cdots,x_n\) 就是起点。
所以把 \(x_1,x_2\) 存进矩阵当起点:
我们往后推一步:
\(mar\cdot\) 变换矩阵\(\,change\) \(=mar^{*}\)。
\(mar^{*}_{\;\;1,1}=F_{i-1}\) 正好就是 \(mar_{2,1}\),根据矩阵乘法的定义,\(mar^*_{\;\;1,1}=mar_{1,1}change_{1,1}+mar_{1,2}change_{2,1}\)。
我们只要恰好一个 \(mar_{2,1}\):所以\(change_{1,1}=0,change_{2,1}=1\)。
同理得:\(change_{1,2}=change_{2,2}=1\)。
所以:
同时,为了好写,我们可以把初始的一行矩阵也写成 \(2\times2\) 的方阵,第二行全是 \(0\) 即可。
【高斯消元】
高斯消元用来解决线性方程组的问题。
例如:
得出 \(x_1=1,x_2=2,x_3=3\)。
这就是线性方程组。
高斯消元法给出了一个普遍性的解决这种问题的方法。
假设我们要解决一个 \(n\) 元的线性方程组,第 \(i\) 个方程是 \(k_{i,1}x_1+k_{i,2}x_2+k_{i,3}x_3+\cdots+k_{i,n}x_n=a_i\)。
我们建立一个 \(n\times (n+1)\) 的矩阵,其中矩阵的第 \(i\) 行为 \((k_{i,1},k_{i,2},\cdots,k_{i,n},a_i)\)。
例如:
我们的目标是得出一个矩阵,这个矩阵左边的 \(n\times n\) 应该是一个单位矩阵。
例如:
这样,第 \(n+1\) 列的所有数就是 \(\{x_i\}\) 的解了。
回到一开始的矩阵,我们考虑考虑怎么做。
我们希望最后第一行第一列的是 \(1\),其他行第一列的都是 \(0\)。
所以我们先让第一行第一列变成 \(1\),也就是除一下:
然后我们用第一行 “消” 掉其他行的 \(x_1\),这就是平时解方程的加减消元法。
然后到 \(x_2\),注意到当我们消完 \(x_1\) 的时候,对之后每一行的乘除都不会影响到第一列的系数了。
因此我们让第二行的第二列变成 \(1\)。
这个时候再用第二行消去其他行的 \(x_2\)。因为第一列已经是 \(0\),所以第二行加减第一行也不会影响 \(x_1\) 的系数 \(1\)。
最后到 \(x_3\),一样的操作。
这样我们就得出了解。
但是!还有情况!无解或者无穷多解怎么办?
考虑一个无解的情况:
\(x_1+x_2=1,2x_1+2x_2=3\)
消去 \(x_1\):
发现,这个时候的最后一行,前面都是 \(0\) 但是最后一列不是。
这表示 \(0\ne 0\),矛盾,所以无解。
因此,只要我们做完高斯消元,发现有一行前面都是 \(0\) 但最后不是 \(0\),说明无解。
再看看无穷多解。
\(x_1+x_2=1,2x_1+2x_2=2\)。
消去。
这个时候最后一行全都是 \(0\),说明无穷多组解。
高斯消元总结:
-
构建矩阵。
-
第 \(i\) 次操作,从 \(i\sim n\) 行中找出一个第 \(i\) 列非 \(0\) 的行,把这个行换到第 \(i\) 行的位置,用这个行消去其他行。
注意:如果找不到非 \(0\) 的行,说明无穷多组解。
-
结束后判断有没有全 \(0\) 的行或者前面全 \(0\) 但最后不是 \(0\) 的行。
【行列式】
行列式定义在一个矩阵 \(M\) 上,记作 \(det(M)\)。
其中 \(sgn(p)=\begin{cases}-1&p\text{是奇排列}\\1& p\text{是偶排列}\end{cases}\) ,也能看出来 \(sgn(p)=(-1)^{inv(p)}\)
行列式有一些性质。
-
将矩阵的某一列乘以一个标量 \(a\) 加到另一列上,行列式不变。
-
交换矩阵的两列,行列式符号取反。
-
将某列整体乘以一个标量 \(a\),行列式也乘以 \(a\)。
-
由于矩阵是对称的,上面关于 "列" 的性质,对 "行" 也同样成立。
【求行列式】
怎么求一个矩阵的行列式?根据这三条性质,有一个 \(O(n^3)\) 的算法。
首先考虑一个下(上)三角矩阵:对角线下方的位置都是 \(0\)。可以发现,这个矩阵的行列式就等于对角线上的数的乘积。
根据性质 "某行加减另一行若干倍,行列式不变" 可以用类似高斯消元的方式把原来的矩阵等价到一个下三角矩阵。
同时,高斯消元法里面会有交换两行的操作。在求行列式的时候,累计交换两行的次数,判断奇偶性,最后再取反即可。
这里可以延伸出一个行列式的性质。
-
如果矩阵存在一些列或行(列向量的集合),它们线性相关,则这个矩阵的行列式为 \(0\)。
证明:如果这个矩阵有一些列或行线性相关,则我们用上面的变换,使矩阵的某一行(列)全为 \(0\),显然可得行列式为 \(0\)。
【柯西-宾内 公式】
Cauchy-Binet 公式可以把两矩阵相乘的行列式拆成两个矩阵分别的行列式。
介绍一下上面式子里的元素。
\(A\) 是一个 \(m\times n\) 的矩阵,\(B\) 是一个 \(n\times m\) 的矩阵,且 \(m\le n\)。
\(S\) 是一个 \(m\) 的大小的 \(\{1,2,\dots,n\}\) 的子集。
\(A_S\) 是从 \(A\) 的一个子矩阵:如果 \(S\) 中包含 \(i\),则 \(A_S\) 中包含 \(A\) 的第 \(i\) 列。这些列顺次排列得到 \(A_S\)。
\(B_S\) 是从 \(B\) 的一个子矩阵:如果 \(S\) 中包含 \(i\),则 \(B_S\) 中包含 \(B\) 的第 \(i\) 行。这些行顺次排列得到 \(B_S\)。
【矩阵树定理】
矩阵树定理能在 \(O(n^3)\) 的时间内求出任意图的生成树个数。
对于一张图 \(G\)(暂时只考虑简单图),构造一个矩阵 \(Q\):
-
\(Q\) 为 \(n\times n\)。
-
\(Q_{i,i}=deg_i\),即 \(i\) 点的度数。
-
\(Q_{i,j}|i\neq j=\begin{cases}-1&\text{i,j 之间有边}\\0&\text{i,j 之间没有边}\end{cases}\)
令 \(M_{11}\) 为 \(Q\) 删去第一行第一列的矩阵,矩阵树定理表明 \(det(M_{11})\) 等于 \(G\) 的生成树个数。
证明:
考虑构造一个 \(n\times m\) 的矩阵 \(E\)。\(E\) 的每一列代表一条边。若第 \(i\) 条边是 \((u_i,v_i)\),则 \(E\) 的第 \(i\) 列中第 \(u_i\) 行设为 \(1\),第 \(v_i\) 行设为 \(-1\),其他行设为 \(0\)。(这里 \(u_i\) 行设为 \(1\),\(v_i\) 行设为 \(1\) 也可以,因为某一列整体乘 \(a\) 行列式不变)
可以发现,\(E\) 第 \(i\) 行所有数的绝对值之和等于 \(i\) 的度数。
观察:\(Q=E\cdot E^T\)。
考虑 \(Q\) 的第 \(i\) 行第 \(i\) 列的元素,也就是 \(E\) 的第 \(i\) 行和 \(E^T\) 的第 \(i\) 列对应相乘后求和。而 \(E^T\) 的第 \(i\) 列就等于 \(E\) 的第 \(i\) 行。那 \(E\) 的第 \(i\) 行与自身相乘答案是多少?答案就是第 \(i\) 行中有多少个非 \(0\) 的元素,就等于 \(i\) 的度数。
对于 \(Q\) 的第 \(i\) 行第 \(j\neq i\) 列的元素,对应到 \(E\) 的第 \(i,j\) 行:当 \(i,j\) 之间没有边,\(E\) 的第 \(i,j\) 行的每一列都至少有一个 \(0\);如果有边,则有一列贡献了 \(-1\)。
观察证毕。
令 \(F\) 为 \(E\) 去掉第一行留下的矩阵,类似观察可以证得 \(M_{11}=F\cdot F^T\)。
这两个矩阵都一样,行列式自然也一样。所以 \(det(M_{11})=det(F\cdot F^T)\)。
运用柯西-宾内(Cauchy-Binet)公式:\(det(M_{11})=det(F\cdot F^T)=\displaystyle\sum_{S}det(F_S)\cdot det(F^T_S)\)。
根据柯西宾内公式的定义,这里枚举的 \(S\) 应该是一个大小为 \(n-1\) 的 \(1\sim m\) 的子集。(\(F\) 是一个 \((n-1)\times m\) 的矩阵)我们发现 \(S\) 其实在 \(F\) 中对应了一颗生成树。
同时注意 \(F^T_S\) 的定义是:抽出 \(F^T\) 在 \(S\) 中的行,而 \(F^T\) 的行就等于 \(F\) 的列,所以 \(det(F_S)\cdot det(F^T_S)=det(F_S)^2\)。
所以 \(det(M_{11})\) 此时已经转到了 \(\displaystyle\sum_{\text{S}}det(F_S)^2\),其中 \(S\) 是一个大小为 \(n-1\) 的边集。
接下来我们要证明:\(det(F_S)=\begin{cases}\pm 1& \text{S 是生成树}\\0&\text{S 不是生成树}\end{cases}\) 。显然有了这个结论就能推出矩阵树定理。
先证明 \(det(F_S)=0\iff\text{S 不是生成树}\)。
由于 \(S\) 是 \(n-1\) 大小的边集,而不是生成树。所以 \(S\) 肯定有一个环:\(p_1,p_2,\dots,p_k\)。
取出这 \(k\) 列,我们发现它们线性相关。所以 \(det(F_S)=0\)。
再证明 \(det(F_S)=\pm 1\iff\text{S 是生成树}\)。我们如果证明了,可以通过交换 \(F_S\) 的两列使得 \(F_S\) 是下三角矩阵且 \(S\) 的对角线全是 \(\pm 1\),也就证明了这个命题。
(这里严格证明不会…… 咕一下)
总之,我们证明了矩阵树定理。
这里再回顾一下矩阵树定理的原本内容:矩阵树定理表明 \(det(M_{11})\) 等于 \(G\) 的生成树个数。
【矩阵树定理的拓展】
矩阵树定理的问题主要有两个方向:改造问题,变成生成树计数相关的问题;或者改造矩阵树定理的矩阵 \(Q\)。
-
非简单图的矩阵树定理。
在构造 \(Q\) 的时候,\(Q_{i,j}|i\neq j\) 不再等于 \(-1\),而是等于 \(-(\text{i,j 之间的边数})\)。
发现这个改动实际上只影响了对于 \(Q=E\cdot E^T\) 的证明,而 \(E\) 的第 \(i,j\) 行的乘积,还是等于 \(-\text{i,j 之间的边数}\)。
-
边带权的矩阵树定理。
发现,矩阵树定理实际上是计算了 \(\displaystyle\sum_{T}\prod_{e\in T}1\),其中 \(T\) 是一颗生成树。
如果给每条边带上权,怎么做?也就是求 \(\displaystyle\sum_{T}\prod_{e\in T}w_e\)。
回想我们矩阵树定理最重要的一步:\(det(F_S)=\begin{cases}\pm 1& \text{S 是生成树}\\0&\text{S 不是生成树}\end{cases}\) ,我们由此推出当 \(S\) 的生成树的时候,答案会贡献 \(1\)。具体的做法是证明可以构造一个等价的下三角矩阵。对角线的乘积为 \(\pm 1\),进而 \(det(F_S)^2=1\)。
现在我们想要让生成树贡献 \(\prod w_e\),也就是让 \(det(F_S)^2=\prod w_e\),也就是 \(det(F_S)=\pm\prod\sqrt{w_e}\),也就是我们要构造一个下三角矩阵,对角线上都是 \(\pm \sqrt{w_e}\)。
我们知道了 \(E\) 怎么构造(注意这里不是 \(Q\) 的构造):对于第 \(i\) 条边 \((u_i,v_i,w_i)\),让第 \(i\) 列的第 \(u_i,v_i\) 行分别等于 \(\pm\sqrt{w_i}\)。
但是我们要求的是 \(Q\),要求的是 \(M_{11}\) 啊?这里有两种办法:\(Q=E\cdot E^T\),和 \(M_{11}=F\cdot F^T\)。
【矩阵树定理的相关题目】
题意:每条边有 \(p_i\) 的概率是好的。求图中有且仅有一颗生成树上的边是好边的概率。\(n\le 50\)。
这里就相当于求 \(\displaystyle\sum_{T}(\prod_{e\in T}p_e)\cdot(\prod_{e\not\in T}(1-p_e))\)。
我们知道矩阵树定理可以求 \(\displaystyle\sum_{T}\prod_{e\in T}p_e\),但是后面那个怎么办?
\(\displaystyle\prod_{e\not\in T}(1-p_e)=\prod_{e\in G}(1-p_e)\div \prod_{e\in T}(1-p_e)\),显然前面那半截可以提出来。
所以 \(\text{原式}=\displaystyle\prod_{e\in G}(1-p_e)\sum_{T}\prod_{e\in T}\dfrac{p_e}{1-p_e}\)。
令 \(w_e=\dfrac{p_e}{1-p_e}\),就变成我们熟悉的形式了。
题意:给定一张图,每条边为黑白色。求恰好有 \(k\) 条黑边的生成树个数。\(n\le 100\)。
借助多项式的系数表示方案数。
考虑重新构造矩阵 \(E\)。(再复习一下,\(E\) 的第 \(i\) 列代表第 \(i\) 条边)
如果边 \(i\) 为黑边,令 \(E\) 的第 \(i\) 列的两个数为 \(\sqrt{x}\) 和 \(-\sqrt{x}\);否则令它们为 \(\pm 1\)。
可能这里会疑惑为什么一定要一正一负:这是为了保证当 \(S\) 不对应生成树的时候,\(det(F_S)=0\)——因为我们要保证环对应的边能线性相关。
为什么要这样做?\(x\) 又代表什么?
首先,\(x\) 是一个形式参数。我们把它放在这里,是因为我们一会要通过多项式运算求方案数。
注意 \((\pm\sqrt{x})^2=x\),所以 \(\displaystyle\sum_{T}\prod_{e\in T}w_e=\sum_{T}x^{\text{T 中黑边个数}}\)。
于是只要我们求出 \(\displaystyle\sum_{T}\prod_{e\in T}w_e\) 的结果(注意这个结果是一个多项式)。其中 \(x^k\) 的系数就是 \(k\) 条黑边的方案数。
但是这还不够,因为在求 \(det(F\cdot F^T)\) 的时候,需要做多项式的运算,每一次复杂度都是 \(O(n\log n)\) 的。太慢了。
我们其实只关心最后每一项的系数。而且因为生成树黑边数量显然 \(\le n-1\),所以最后的多项式最多 \(n-1\) 次。所以可以使用拉格朗日插值公式,令 \(x\) 为 \(n\) 个不同的值分别代入,可以求得最终多项式的系数。