【小结】线性代数
置顶
矩阵
矩阵:由 \(m\times n\) 个数排成的 \(m\) 行 \(n\) 列的数表,记作 \(A_{m\times n}\),其中第 \(i\) 行第 \(j\) 列元素记作 \(A_{i,j}\)。
方阵:行数列数相等的矩阵。
零矩阵:所有元素均为 \(0\) 的矩阵,记为 \(O\)。
单位矩阵:主对角线元素为 \(1\),其余元素为 \(0\) 的方阵,记为 \(I\)。
对于任意方阵 \(A\),\(A\times I=I\times A=A\)。
矩阵加法:\((A+B)_{i,j}=A_{i,j}+B_{i,j}\)。
矩阵数乘:\((kA)_{i,j}=k\times A_{i,j}\)。
矩阵乘法:
\(A\) 是 \(m\times p\) 矩阵,\(B\) 是 \(p\times n\) 矩阵,则他们的乘积 \(C=A\times B\) 是一个 \(m\times n\) 矩阵,其中:
\(C_{i,j}=\sum_{k=1}^{p} A_{i,k}\times B_{k,j}\)。
结果矩阵的第 \(i\) 行第 \(j\) 列元素,等于 \(A\) 的第 \(i\) 行与 \(B\) 的第 \(j\) 列对应元素乘积之和。
性质:
-
有结合律
-
无交换律。
矩阵乘法优化 DP
以 \(f_i=f_{i-1}+f_{i-2}\) 为例。
注意到仅与相邻 \(2\) 项有关,那么构建一个 \(2\times 2\) 的矩阵。
一开始向量是 \((1,1)\)。竖着的。
那么考虑如何构建一个矩阵 \(A\),使得 \(A\times(f_{i-1},f_{i-2})\to (f_i,f_{i-1})\)。
那么这个矩阵可以是:
\(11\)
\(10\)
然后因为有结合律,所以可以快速幂维护矩阵乘法。
具体矩阵快速幂的结构体写法:
struct Matrix
{
int n,m;
vector<vector<int> > a;
Matrix(int nn,int mm):n(nn),m(mm),a(nn,vector<int>(mm,0)){}
Matrix operator*(const Matrix &b)const
{
Matrix res(n,b.m);
int i,j,k;
for (i=0;i<n;i++)
{
for (k=0;k<m;k++)
{
if (!a[i][k]) continue;
for (j=0;j<b.m;j++) res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
}
}
return res;
}
};
Matrix qp(Matrix a,int b)
{
Matrix res(m,m);
for (i=0;i<m;i++) res.a[i][i]=1;
while (b)
{
if (b&1) res=res*a;
a=a*a;
b>>=1;
}
return res;
}
然后对于很多 DP,只与前面几项有关,那就可以用矩阵加速。
还有一种题,就是最短路路径长度固定。求方案数。这种问题可以用快速幂倍增,然后根据结合律,每次都可以跑 floyd。这就相当于 \(d\) 次 floyd。
高斯消元
高斯消元是解 \(n\) 元一次方程组的一个算法。
\(n\) 元一次线性方程组:
\(a_{11}x_1+a_{12}x_2+\dots+a_{1n}x_n=b_1\)
\(\dots\)
\(a_{n1}x_1+a_{n2}x_2+\dots+a_{nn}x_n=b_n\)
现在有一个定义,是增广矩阵,对于如上的方程,定义如下:
\(a_{11} a_{12} \dots a_{1n} b_1\)
\(a_{21} a_{22} \dots a_{2n} b_2\)
\(\dots\)
\(a_{n1} a_{n2} \dots a_{nn} b_n\)
高斯消元的本质是对增广矩阵做不改变方程组解的变换,这就是初等行变换,共有 \(3\) 种:
-
交换 \(2\) 行
-
把某行的数乘一个非零常数 \(k\)
-
把某行乘 \(k\) 倍加至另一行
阶梯形矩阵:
高斯消元的目标就是将增广矩阵转化为三角阶梯形矩阵:
\(a_{11} a_{12} \dots a_{1n} b_1\)
\(0a_{22}\dots a_{2n} b_2\)
\(00a_{33}\dots a_{3n} b_3\)
\(\dots\)
\(000000\dots a_{nn}b_n\)
然后就可以通过从后往前计算 \(x_{n\sim 1}\) 然后回代算出答案。
矩阵的秩:
将矩阵转化为阶梯矩阵后,非零行的数量称之为矩阵的行秩。
矩阵的列秩同理。行秩=列秩。统称为矩阵的秩。
线性方程组解的分布:
对于 \(n\) 个未知数,\(m\) 个方程构成的线性方程组,其增广矩阵为 \(m\) 行 \(n+1\) 列,利用初等行变换,化简为阶梯矩阵,设矩阵的秩为 \(R\)。
情况 \(1\):无解
系数矩阵的秩<增广矩阵的秩
情况 \(2\):无数解
增广矩阵的秩<n
情况 \(3\):唯一解
系数矩阵的秩=增广矩阵的秩=n
高斯消元的原理:前向消元(化为三角矩阵)+回代求解
-
选主元(数学可以任意选一个主元,但在信息中选绝对值最大的减小精度误差)设主元是 \(a_{ii}\),那么对于下面的,要消元,令 \(k=a_{ji}/a_{ii}\),然后第 \(j\) 行减去第 \(i\) 行乘 \(k\),这样就消掉了。这就是对于每一列 \(i\),消去 \([i+1,n]\)。
-
回代 一步步倒着回代即可。
高斯-约旦消元法:
变成最简行阶梯矩阵可以不用回代。
每次在第 \(i\) 列确定最大系数 \(a_{ii}\) 后,将第 \(i\) 行同时除以 \(a_{ii}\),这样 \(a_{ii}\) 就变成了 \(1\)。然后第 \(i\) 列所有元素也可以通过同样的消元变成 \(0\)。最后 \(x_i=a_{i,n+1}\)。
一般都是用这种算法因为更好写。
时间复杂度:\(\mathcal O(n^3)\)。
注意:先判无解,后判无数解。
但是注意:这一个东西是有问题的。在高斯消元的模板中体现不出来,但是在 P2455 能体现出来。
HACK:
4
0 0 2 1 2
0 0 0 1 1
0 0 0 0 0
0 0 1 1 1
OUTPUT:
-1
WRONG OUTPUT:
0
我们惊奇的发现这个数据很 6,它看似无数解实则无解。来看看为啥。
首先第 \(1\) 列我们会跳过。然后第 \(2\) 列我们也会跳过。但是第 \(3\) 列我们还是会跳过。因为找不到主元。
但是这一步是错误的。为啥捏?
因为主元不在下面,而是在上面。
所以如果上面的那个没有被当做过主元,可以当这个的主元。
这下,高斯消元的代码就彻底正确了。可以解决一些题目了。
模板代码看 P2455 不要看高斯消元板子。
线性基
问题:求一组数的最大异或和。
发现难点在于这组数的数量太多。考虑能不能用很少的数代替这个很长的序列。
首先定义一个东西。
线性有关:存在一组数 \(s_1,s_2,\dots,s_n\) 满足 \(s_1a_1\oplus s_2a_2\oplus \dots \oplus s_na_n=0\)。
线性无关:不存在上述数组。
那我们考虑如果这个线性基线性有关的话那就很浪费。
我们现在需要找出最短的,和原序列本质相同的一个序列。这玩意就叫线性基。
但其实线性基不只能搞异或的问题,其他问题有些可以结合高斯消元。
但先考虑异或。
用 \(p_i\) 表示二进制下最高位在 \(2^i\) 的基。
那输入 \(n\) 个数,依次插入。设目前插入的值是 \(x\)。
遍历 \(i=63\sim 1\)。如果 \(p_i\) 上没有值,那直接填上。结束。
如果 \(p_i\) 有值,那就让 \(x\oplus p_i\to x\)。然后继续做。容易发现 \(a,b\) 和 \(a,a\oplus b\) 是本质相同的。能异或出的值都是 \(a,b,a\oplus b\)。所以这样是没问题的。
那么我们就得到了一个最短的线性基。
然后最好是再简化一下,遍历 \(i,j\),其中 \(i<j\),如果 \(p_j\) 在 \(i\) 这一位也有值的话,那就异或一下。
如此操作之后所有基上的位都没有相同的位,而且它是最短的,长度不会超过 \(log\)。所以这样就可以了。
得到标准线性基之后,可以干如下事情:
-
查询最大异或和。直接输出线性基的异或和。
-
查询最小异或和。直接输出最小的那个基。
-
查询一个数 \(x\) 是否能被其他数异或出来。二进制分解。
-
查询异或第 \(k\) 小。可以遍历这个基,然后二进制分解一下,即可。

浙公网安备 33010602011771号