线性代数入门


1. 高斯消元

模板题

定义以下三种操作为 初等行变换

  1. 将某一行乘上 \(c\)
  2. 将某一行的 \(c\) 倍加到另一行
  3. 交换两行

这里介绍高斯-约旦消元法,利用初等行变换将矩阵转化成对角矩阵,然后就很容易求出解。

  1. 枚举 \(i\) 表示现在要消去第 \(i\)
  2. \([i,n]\)​ 内选择一个 \(k\)​ 满足 \(a[k][i]\neq 0\)​,若不存在则说明无解
  3. 交换第 \(i\) 行和第 \(k\)
  4. 对于 \([i+1,n]\)​ 内所有 \(j\)​,将第 \(j\)​ 行减去 \(\dfrac{a[j][i]}{a[i][i]}\) 倍的第 \(i\) 行​

容易发现,最后第 \(i\)​ 项系数只会出现在第 \(i\)​ 行。并且任意时刻,第 \(i\)​ 行的 \(1\dots i-1\)​ 项系数都为 \(0\)​​,所以不会对其他方程的这些项造成影响。

inline bool zero(double t) {
	return fabs(t) < 1e-8;
}

signed main() {
	scanf("%d", &n);
	rep(i, 1, n) rep(j, 1, n + 1)
		scanf("%lf", &a[i][j]);
	rep(i, 1, n) {
		k = i;
		if(zero(a[i][i])) rep(j, i + 1, n) if(!zero(a[j][i])) { k = j; break; }
		if(i ^ k) rep(j, i, n + 1) swap(a[i][j], a[k][j]);
		if(zero(a[i][i])) return puts("No Solution") & 0;
		rep(j, 1, n) if(i != j) {
			t = a[j][i] / a[i][i];
			rep(k, i, n + 1) a[j][k] -= a[i][k] * t;
		}
	}
	rep(i, 1, n) printf("%.2lf\n", a[i][n + 1] / a[i][i]);
	return 0;
}

2. 行列式

对于一个方阵,其行列式是线性变换的伸缩因子。例如在三维空间中,行列式表示线性变换造成的体积放大倍率。

代数定义:\(\det A=|A|=\sum\limits_{p是n的排列}(-1)^{p的逆序对数}\prod\limits_{i=1}^na_{i,p_i}\)​​​

看右边那串东西,其实是从方阵中选出 \(n\)​ 个数,使得没有两个数在同一行或同一列,然后把它们乘起来。所以如果选出的数中有一个 \(0\) 就没有贡献了。

排列的性质

  1. 交换两数,逆序对数的奇偶性改变
  2. \(n\ge 2\) 时,奇偶排列(逆序对数为奇 / 偶数的排列)各占一半

行列式的性质

  1. \(|M|=|M^T|\)
  2. 交换两行,行列式反号
  3. 用一个数乘行列式的某行,等于用这个数乘此行列式
  4. 如果行列式中有两行成比例,则行列式等于 \(0\)(先把比例系数提出来,发现两行相同了,交换两行行列式不变。但根据性质 2,行列式反号了,所以只能为 \(0\)
  5. 若行列式中某一行是两组数之和,则这个行列式等于两个行列式之和,这两个行列式分别以这两组数为该行,而其余各行与原行列式对应各行相同。即:\(\left|\begin{matrix}\dots\\a_{i,1}+b_{i,1},a_{i,2}+b_{i,2}\dots a_{i,n}+b_{i,n}\\\dots\end{matrix}\right|=\left|\begin{matrix}\dots\\a_{i,1},a_{i,2}\dots a_{i,n}\\\dots\end{matrix}\right|+\left|\begin{matrix}\dots\\b_{i,1},b_{i,2}\dots b_{i,n}\\\dots\end{matrix}\right|\)
  6. 将某一行的倍数加到另一行,行列式的值不变
  7. \(\left|\begin{matrix}A~0\\C~B\end{matrix}\right|=|A||B|\)​,其中 \(A,B\)​​ 是方阵 (从选数的角度考虑)
  8. 一个矩阵的行列式可以按行展开,即:\(\left|\begin{matrix}\dots\\a_{i,1},a_{i,2}\dots a_{i,n}\\\dots\end{matrix}\right|=\left|\begin{matrix}\dots\\a_{i,1},0\dots 0\\\dots\end{matrix}\right|+\left|\begin{matrix}\dots\\0,a_{i,2},0\dots 0\\\dots\end{matrix}\right|+\dots+\left|\begin{matrix}\dots\\0,\dots 0,a_{i,n}\\\dots\end{matrix}\right|\)​​​​​(还是从选数的角度理解,第 \(i\)​​​​​ 行只能选一个数,选 \(a_{i,1},a_{i,2},\dots,a_{i,n}\)​​​​​ 的方案是独立的)。进一步地,定义代数余子式:\(A_{i,j}=(-1)^{i+j}|M_{i,j}|\)​​​​​,其中 \(M_{i,j}\)​​​​​ 是原矩阵删去第 \(i\)​​​​​ 行和第 \(j\)​​​​​ 列得到的矩阵。一个矩阵的行列式,等于它某一行中,每个元素乘上它的代数余子式的和。即:\(|B|=\sum\limits_{j=1}^nb_{i,j}A_{i,j}=(-1)^{i+j}b_{i,j}|M_{i,j}|\)​​​​​​​(展开后,每个矩阵的第 \(i\)​​​​​ 行只有一个数,用 \(i+j-2\)​​​​​ 次交换邻行邻列把它交换到 \((1,1)\)​​​​​,然后用性质 7)
  9. 上(下)三角矩阵的行列式为其主对角线元素之积。

行列式求值

模板题

现在考虑如何计算一个矩阵的行列式。观察到第 9 条性质,我们可以把矩阵消成上三角矩阵,同时注意符号的变化,然后直接得出答案。

但当矩阵内都是整数时,仍会涉及实数运算,导致精度较低。考虑一种辗转相除的方法:每次选定两行 \(i,j\)​​,将第 \(j\)​​ 行尽可能多地减去第 \(i\)​​ 行,然后交换这两行,直到 \(a_{i,i}=0\)​。这样时间复杂度是 \(O(n^3+n^2\log V)\)​ 的。

rep(i, 1, n) rep(j, i + 1, n) {
	while(a[i][i]) {
		t = a[j][i] / a[i][i];
		rep(k, i, n) a[j][k] = (a[j][k] - a[i][k] * t % p + p) % p;
		swap(a[i], a[j]);
		ans = -ans;
	}
	swap(a[i], a[j]);
	ans = -ans;
}
if(ans < 0) ans += p;
rep(i, 1, n) (ans *= a[i][i]) %= p;

3. 矩阵求逆

模板题

对于矩阵 \(A\),若存在矩阵 \(B\) 使得 \(AB=I\)\(I\) 是单位矩阵),则 \(B\)\(A\) 的逆,也可写作 \(A^{-1}\)

对矩阵进行高斯消元时,我们发现可以仅用初等行变换将矩阵变成单位矩阵,而每一种初等行变换都可以表示成一次矩阵乘法。即 \(AP_1P_2\dots P_k=I\)。那么 \(P_1P_2\dots P_k\) 不就是答案吗?

我们可以在高斯消元时记录下所有操作,然后搞一个单位矩阵,再把这些操作做一遍。或者更方便地,我们在原矩阵右边添加一个单位矩阵,把左边消成单位矩阵,右边就求出了逆。

若原矩阵不能消成单位矩阵,则原矩阵不可逆。

n = read();
rep(i, 1, n) rep(j, 1, n) a[i][j] = read();
rep(i, 1, n) a[i][i + n] = 1;
rep(i, 1, n) {
	if(!a[i][i]) rep(j, i + 1, n) if(a[j][i]) { swap(a[i], a[j]); break; }
	if(!a[i][i]) return puts("No Solution") & 0;
	tmp = poww(a[i][i]);
	rep(j, 1, n) if(i != j) {
		t = a[j][i] * tmp % P;
		rep(k, 1, n * 2) a[j][k] = (a[j][k] - a[i][k] * t % P + P) % P;
	}
	rep(j, i, n * 2) (a[i][j] *= tmp) %= P;
}
rep(i, 1, n) {
	rep(j, n + 1, n * 2)
		printf("%lld ", a[i][j]);
	putchar(10);
}

4. 特征值与特征向量

有时,对一个向量进行一次线性变换(左乘一个矩阵),这个向量方向不变,只是长度发生了变化,即 \(Av=\lambda v\)​​​。也可以表示成 \((A-\lambda I)v=0\)​​

对于一个矩阵 \(A\)​​​​,若存在数 \(\lambda\)​​​​ 和向量 \(v\)​​​​ 使得 \(Av=\lambda v\)​​​​,称 \(\lambda\)​​​​ 为矩阵 \(A\)​​​​ 的 特征值\(v\)​​​​ 为 特征向量。同时定义 \(f(x)=|xI-A|\)​​​​ 为 特征多项式\(|xI-A|=0\)​​​​ 为 特征方程

定理 \(n\) 阶矩阵 \(A\)\(n\) 个特征值,为其特征方程的 \(n\) 个根。特征值 \(\lambda\)​ 对应的特征向量为 \((\lambda I-A)x=0\)​ 的非零解。

注意一个特征值对应无穷多个特征向量,因为可以对向量进行数乘,仍满足定义。

矩阵对角化

相似矩阵:对于两个矩阵 \(A,B\)​,若存在可逆矩阵 \(P\)​ 使得 \(P^{-1}AP=B\)​,则 \(A,B\)​ 相似。

考虑矩阵 \(A\) 和对角矩阵 \(\Lambda=\left[\begin{matrix}\lambda_1\\&\lambda_2\\&&\ddots\\&&&\lambda_n\end{matrix}\right]\) 相似的条件。设矩阵 \(P\)\(n\) 个列向量构成即 \(P=[p_1,p_2,\dots,p_n]\),且 \(P\)​ 可逆

\(A[p_1,p_2,\dots,p_n]=[p_1,p_2,\dots,p_n]\Lambda\)\([Ap_1,Ap_2,\dots,Ap_n]=[\lambda_1p_1,\lambda_2p_2,\dots,\lambda_np_n]\)

那么 \(Ap_i=\lambda_ip_i\)。这不就是特征值和特征向量的定义吗?

于是有 \(A=P\Lambda P^{-1}\)​​​,其中 \(\Lambda\)​ 是由 \(A\)​ 的所有特征值构成的对角矩阵,\(P\)​​ 的第 \(i\)​ 列是特征值 \(\lambda_i\)​​​ 对应的特征向量。

于是我们可以快速计算一些矩阵的幂,\(A^n=(P\Lambda P^{-1})^n=P\Lambda^nP^{-1}\)​。

递推数列通项公式

这里只讨论二阶齐次线性递推数列。

首先我们可以直接用上文的结论。​比如斐波纳契转移矩阵 \(\left[\begin{matrix}1~1\\1~0\end{matrix}\right]\)​​​​,特征方程 \(\left|\begin{matrix}\lambda-1~-1\\-1~\lambda\end{matrix}\right|=0\)​​​​ 即 \(\lambda^2-\lambda-1=0\)​​​​,解得 \(\lambda=\dfrac{1\pm\sqrt 5}{2}\)​​​​,并分别求出特征向量 \([1,\dfrac{\sqrt 5-1}{2}]^T,[1,-\dfrac{\sqrt 5+1}{2}]^T\)​​​​​​。​然后一顿爆算求出 \(P\)​​​​​​ 的逆 \(\left[\begin{matrix}\dfrac{5+\sqrt5}{10}~\dfrac{\sqrt5}{5}\\\dfrac{5-\sqrt5}{10}~-\dfrac{\sqrt5}{5}\end{matrix}\right]\)​​​​​​。把 \(P,\Lambda^n,P^{-1}\)​​​​​​ 依次乘起来,最后乘上 \([1,0]^T\)​​​​​​,就可得出通项公式 \(f_n=\dfrac{\sqrt 5}{5}\left[(\dfrac{1+\sqrt5}{2})^n-(\dfrac{1-\sqrt5}{2})^n\right]\)​​。​

这么麻烦,为什么不用生成函数呢

考虑一个数列 \(f_i=pf_{i-1}+qf_{i-2}\)​,其中 \(f_0,f_1\) 已知

尝试构造等比数列:设存在 \(a,b\) 使得 \(f_{i+1}-af_i=b(f_i-af_{i-1})\)​,即 \(f_{i+1}=(a+b)f_i-abf_{i-1}\)

发现 \(a,b\)​ 是方程 \(x^2-px-q=0\)​ 的根。而这个方程就是转移矩阵的特征方程

所以 \(\{f_{i+1}-af_i\}\)​ 是公比为 \(b\)​ 的等比数列,有 \(f_{i+1}-af_i=b^i(f_1-af_0)\)​。

又发现 \(a,b\) 也满足 \(f_{i+1}-bf_i=a(f_i-bf_{i-1})\)

所以 \(\{f_{i+1}-bf_i\}\) 是公比为 \(a\) 的等差数列,有 \(f_{i+1}-bf_i=a^i(f_1-bf_0)\)​。​

两式相减,得到 \(f_i=\dfrac{f_1-af_0}{b-a}b^i+\dfrac{f_1-bf_0}{a-b}a^i\)

其实并不用每次推。可以设 \(f_i=\alpha a^i+\beta b^i\)​,解一个方程就完了

比如斐波纳契数列,\(a=\dfrac{1+\sqrt 5}{2},b=\dfrac{1-\sqrt 5}{2}\),设 \(f_i=\alpha a^i+\beta b^i\),则 \(\begin{cases}f_0=\alpha +\beta=0\\f_1=\frac{1+\sqrt 5}{2}\alpha+\frac{1-\sqrt 5}{2}\beta\end{cases}\)

解得 \(\alpha=\dfrac{\sqrt 5}{5},\beta=-\dfrac{\sqrt 5}{5}\),那么 \(f_n=\dfrac{\sqrt 5}{5}\left[(\dfrac{1+\sqrt5}{2})^n-(\dfrac{1-\sqrt5}{2})^n\right]\)​。​

对于更高阶的情况,记个结论:设 \(f_i=\alpha a^i+\beta b^i+\gamma c^i+\dots\)​,列方程组​

例题 - 块速递推

常系数齐次线性递推

模板题

首先可以写出一个 \(k\times k\) 的转移矩阵:\(A=\left[\begin{matrix}f_1~f_2~f_3~\dots f_{k-1}~f_k\\1~~~0~~~0~~\dots~~~0~~~0\\0~~~1~~~0~~\dots~~~0~~~0\\0~~~0~~~1~~\dots~~~0~~~0\\\vdots~~~\vdots~~~\vdots~~~\ddots~~~\vdots~~~\vdots\\0~~~0~~~0~~\dots~~~1~~~0\end{matrix}\right]\)

初始矩阵 \(B=[a_{k-1},a_{k-2},\dots,a_0]^T\)​​,答案是 \((A^nB)_k\)​​。

凯莱-哈密顿定理:对于矩阵 \(A\)​​​,\(f(x)=|xI-A|\)​​​ 为其特征多项式,有 \(f(A)=O\)​​​,其中 \(O\)​​​ 是零矩阵。

本题中,可以用行列式性质 7 和 8 计算出 \(f(x)=x^k-f_1x^{k-1}-f_2^{k-2}-\dots-f_k\)

那么只需计算 \(g(x)=x^n\bmod f(x)=\sum\limits_{i=0}^{k-1}g_ix^i\)​,答案为 \((g(A)B)_k=(\sum\limits_{i=0}^{k-1}g_iA^iB)_k=\sum\limits_{i=0}^{k-1}g_i(A^iB)_k=\sum\limits_{i=0}^{k-1}g_ia_i\)​。

计算 \(g(x)\) 可以用倍增 + 多项式取模。时间复杂度 \(O(k\log k\log n)\)​。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM