线性代数

基本概念

矩阵乘法

基本概念

对于一个 \(n\times p\)\(p\times m\) 的矩阵做矩阵乘法可以得到一个 \(n\times m\) 的矩阵。

\[A_{i,k}=\sum\limits_{i=1}^n\sum\limits_{j=1}^p\sum\limits_{k=1}^mB_{i,j}\times C_{j,k} \]

矩阵乘法具有结合律,但是没有交换律。其中结合律为我们用线段树或者倍增之类的结构维护矩阵乘法提供了依据。

优化 DP 的时候可以看成贡献系数,比如对于 \(f\to g\) 的单维度转移,也就是两个向量之间的转移,可以用向量乘以矩阵得到向量来求解。对于 \(i\to j\) 的转移,其系数就是矩阵中的 \((i,j)\) 位置上的数。常用于动态 DP 的求解。

应用

P7453 [THUSC 2017] 大魔法师(线性变换)

假设我们现在有一个向量 \(\vec{A}\),我们想将其变成 \(\vec {A'}\)

\[\vec{A}=\{a,b,c,d,e\}\to\vec{A'}=\{12a+2b+4d,b+1+d,a+b+4c,100d,114514\} \]

数字是瞎写的,但是体现了线性变换的过程。线性变换可以用矩阵来刻画。如果有赋值操作和加一个常数的操作,就需要我们给向量手动多开一个常数维度,初始为 \(1\) 就行了。

根据 \(A\times B\to A'\),可以得到 \(A'_k\gets A_j\times B_{j,k}\)。所以 \(B_{i,j}\) 就是 \(A_i\) 对于 \(A'_j\) 的贡献系数。

本题设计出矩阵之后,直接使用线段树维护矩阵就行了。

P10102 [GDKOI2023 提高组] 矩阵

判定取模意义下的矩阵乘法结果是否成立。暴力矩阵乘法的时间复杂度是立方的会超时。

考虑随机一点的东西,我们对于等式两边都左乘一个相同的随机向量,这样子向量乘以矩阵是 \(O(n^2)\) 的。

这是一个必要不充分条件,但是失败的概率小于 \(\dfrac{1}{P}\)

P6569 [NOI Online #3 提高组] 魔法值(辅助 DP 转移)

图上阶段数很大的转移,考虑用 DP 值构成的向量去乘以带着贡献系数的邻接矩阵。

询问的时候如果直接矩阵快速幂是 \(O(qn^3\log V)\),提前处理 \(2^i\) 的邻接矩阵自己乘自己,然后询问的时候拿向量来乘矩阵之后每次得到的都是向量,向量乘以矩阵是平方的,单次乘法的复杂度少一个 \(n\),就是 \(O(qn^2\log n)\) 了。

QOJ10520. 矩阵除法(模 2 意义下的矩阵求逆)

太深刻了,考虑矩阵乘法的本质,就是 \(A\to C\) 的一个变换,其中加权系数矩阵为 \(B\)

行间独立,也就是 \(A\) 的第 \(i\) 行转移到 \(C\) 的第 \(i\) 行,至于这一行内每一列的权值,那就是行内加权了,加的权重为 \(B\) 的行内的值,\(B\) 的列表示对于 \(C\) 的每一列其在自己行内的加权系数相同。

那么转化为 \(01\) 形态的矩阵,就是是否选择了。\(B\) 的每一列独立,考虑对于列单独做,\(B\) 的每一列的若干个数就是最终 \(C\) 那一列的加权。

于是 \(B\) 某一列代表的就是从 \(A\) 中选择若干列,他们异或起来等于 \(C\) 中的某一列。

使用线性基即可,再用 std::bitset 优化可以做到 \(O(\dfrac{n^3}{w})\)

QOJ6504. Flower's Land 2(逆矩阵的应用)

首先有一个很重要的观察,两个位置在最后如果能被消除,那么一定奇偶性不同。

考虑非修改版本,在 \(i=2k\) 的位置放上 \(s_{a_i}\),在 \(i=2k+1\) 的位置放上 \(s_{a_i}^{-1}\),一个区间能被消除需要满足其矩阵乘法之后的结果为单位矩阵。

考虑带上修改,发现不管怎么加,一个节点的可能形态只有 \(3\) 种,也就是区间加 \(0,1,2\) 之后的矩阵,我们维护加法 tag,根据目前的形态切换该节点的矩阵即可。

时间复杂度 \(O((n+q)\log n)\)

行列式

基本概念

  • 记作 \(\det(A)\) 或者 \(\lvert A\rvert\)

求值:\({\rm det}(A)=\sum\limits_p (-1)^{f(p)}\prod A_{i,p_i}\),其中 \(f(p)\)\(p\) 的逆序对数,\(p\) 取遍 \(1\sim n\) 的排列。

如果没有 \(-1\) 的系数就是积和式了,但是目前无多项式复杂度求解。

性质

  • \(\lvert I\rvert=1\)

  • 上三角(右上)矩阵的值为主对角线乘积。(求解行列式的基础)

  • 交换矩阵两行,行列式变号

  • 矩阵乘上一常数,行列式也相应乘上一常数

  • 当矩阵有两行相等或者呈倍数关系,行列式为 \(0\)

  • 若两矩阵至多一行不相等,则将这一行相加所得矩阵的行列式为原来两个之和。

  • 矩阵某一行加上另一行倍数,行列式不变。

例题

P7112 【模板】行列式求值

  while(a[i][i]){
  	int p=a[j][i]/a[i][i];
  	for(int k=i;k<=n;k++) a[j][k]=(a[j][k]-1ll*p*a[i][k]%mod+mod)%mod;
  	swap(a[i],a[j]); t*=-1;
  }
  swap(a[i],a[j]); t*=-1;

如果模数不是质数的话,使用辗转相除法。

利用初等变换将矩阵变成上三角矩阵,然后值就是对角线乘积。

注意细节如果交换两行,需乘以 \(-1\)

P6113 【模板】一般图最大匹配

咕咕咕,以后再补。先放一个链接

想不到吧,这种图论难题也存在线性代数做法。

考虑随机生成一个数组 \(a_{i,j}\) 满足 \(a_{i,j}=a_{j,i}\)。假如存在边 \((i,j)\)\(i<j\)),我们就在 \((i,j)\) 位置填上 \(a_{i,j}\),且在 \((j,i)\) 填上 \(-a_{j,i}\)

Tutte 定理:如果图存在完美匹配,当且仅当 \(\det(A)\neq 0\)

证明就是先证明图存在完美匹配当且仅当可以用若干偶环(包括二元环)来覆盖整张图。

对于奇偶环讨论一下,然后会消掉的。

推论是最大匹配数就是 \(\dfrac{\mathrm{rank(A)}}{2}\),高斯消元可解。

其中随机数 \(a_{i,j}\in [0,P-1]\),在模 \(P\) 的意义下求解。

对于多项式 \(\sum a_ix^i\equiv 0\pmod P\),错误率是 \(\dfrac{n}{P}\)

同时,我们还需要构造方案。

高斯消元

P4783 【模板】矩阵求逆

\(A^{-1}A=I\),将矩阵乘法看成线性变换。

对于 \(A\) 做一个 \(A^{-1}\) 的线性变换可以得到 \(I\),对于 \(I\) 做一个 \(A^{-1}\) 的线性变化可以得到 \(A^{-1}\)

注意到 \(A\)\(I\) 的线性变化过程是相同的(都是 \(A^{-1}\)),所以我们在对于 \(A\) 线性变换成 \(I\) 的时候,对于 \(I\) 做同样的操作,就可以把 \(I\) 变成 \(A^{-1}\),也就得到了 \(A^{-1}\)。很巧妙吧。

P3389 【模板】高斯消元法

消成上三角矩阵之后,倒着一行一行求解。时间复杂度 \(O(n^3)\)

P2455 [SDOI2006] 线性方程组

加入了对于无解和无数解的判断,有点小麻烦。两者的主要区别就在于左侧系数为 \(0\) 的时候,右侧是否为 \(0\)

无数解就是系数为 \(0\),等号另一侧也为 \(0\)。无解就是系数为 \(0\),等号另一侧不为 \(0\)

需要注意的是如果遇到有一个无解那么肯定整体无解,但是如果遇到有一个无数解,那么也可能最终无解,所以需要处理所有方程。当我们在处理过程中遇到所有 \(x_i\) 的系数都为 \(0\) 的时候就跳过去去处理 \(x_{i+1}\),可以采用 \(cnt\) 记录已处理方程数,对于每个主元 \(x_i\) 对编号在 $ > cnt$ 之后的所有方程进行操作,而非对于 \(\ge i\) 的。这样最后剩下的 \([cnt+1,n]\) 即为各项系数全部为 \(0\) 的方程,判断一下即可。

P4035 [JSOI2008] 球形空间产生器

解多元二次方程题,可得到对于 \(\forall i \in [1,n+1]\)\(\sum\limits_{j=1}^n(x_j-c_{i,j})^2=R^2\)
展开可得 \(\sum\limits_{j=1}^n x_j^2-2x_jc_{i,j}+c_{i,j}^2=R^2\)

观察一下形式,有平方项显然不太好处理,注意 \(c_{i,j}\) 为已知,所以这个无需处理。我们发现 \(R\) 与题无关显然不用求,于是考虑相邻两个式子作差,\(x_j^2\) 平方项以及 \(R^2\) 就消掉了。直接高斯消元即可。

P2447 [SDOI2010] 外星千足虫

加法同余式转化为异或方程组,可得:

\[\bigoplus\limits_{j=1}^n a_{i,j}\times x_j=b_i \]

注意这里是贪心最少的方程个数,所以方法就是尽可能在前面几个方程里面找就行了。
可以用 bitset 快速消元,时间复杂度 \(O(\dfrac{n^3}{w})\)

矩阵树定理

将度数矩阵和邻接矩阵作差之后任意去掉一行求行列式。

  • 无向图

\(D_{i,j}=\begin{cases} deg_i&i=j \\0&i\neq j \end{cases}\)
\(A_{i,j}=e_{i,j}\) (其中 \(e_{i,j}\) 代表 \(i \to j\) 重边数量)。
于是得到 \(L=D-A\),将 \(L\) 去掉第 \(i\) 行和第 \(i\) 列,其中 \(i\) 任选,得到的矩阵求行列式即可。

  • 有向图

对于有向图就是把度数矩阵改为入度或者出度,根据要求的外向树还是内向树来决定使用入度还是出度。同时去掉的那一行和一列必须为 \(root\)。注意外向树答案为入度统计,而内向树是出度统计。

可以广义扩展一下,其实就是所有树边多项式乘积之和。

P6178 【模板】Matrix-Tree 定理

当生成树边权为所有边的乘积的时候,直接将边权改为重边即可。

P6624 [省选联考 2020 A 卷] 作业题

等学完了莫比乌斯反演在来写这题。

P4336 [SHOI2016] 黑暗前的幻想乡

P3317 [SDOI2014] 重建

P10881 「KDOI-07」能量场

P5807 【模板】BEST 定理 | Which Dreamed It

\(1\) 为起点,除了起点,其他点的最后一条出边不形成环,所以所有最后一条出边就是以 \(1\) 为根的内向树,钦定完了最后一条出边之后,剩下的边以任意顺序访问,是一个阶乘的形式。

因此有向图的欧拉回路个数:\(\prod\limits_u(deg_u-1)!\times\) 以某点为根的内向树个数

注意上述定理情况是没有指定根的情况,其去掉了循环同构。如果固定了起点 \(s\) 的话,就是 \(deg_s!\) 了,所以我们需要额外 \(\times deg_1\)

注意特判掉不存在欧拉回路,对于孤立点我们对其打一个标记,然后求行列式之类的时候跳过它即可。求生成树个数直接套用 Matrix-Tree 定理即可。

线性基

给定一组向量 \(\{ \vec{a_i} \}\),求他们的一组基底 \(\{ \vec{b_i} \}\) 使得任意一个 \(a_i\) 都可以通过 \(b_j\) 线性组合出来。

在 OI 范围内的应用一般是二进制异或线性基。

P3265 [JLOI2015] 装备购买

向量版本的线性基。

我们每次不断插入向量,从高位到低位来判断,如果该维度没有,那就用当前向量表示,否则把当前向量的当前维度使用之前在这一位的基来消为 \(0\),然后做下一维度。

P3421 [POI2005] SKO-Knights

即求 \(n\) 个二维向量的大小为 \(2\) 的线性基。

注意不同于上一题中的实系数,本题是整系数,整系数除法不具有可逆性,所以我们只能用加减法。

我们维护线性基内的两个向量 \(\vec{a},\vec{b}\),考虑加入一个向量 \(\vec{c}\),在我们对于 \(\vec{a},\vec{b}\)\(x\) 这一维上进行辗转相减,对于 \(\vec{a},\vec{c}\) 也在 \(x\) 这一维度上辗转相减,然后令 \(y_b\gets \gcd(y_b,y_c)\) 即可。

P3812 【模板】线性基

每次插入一个数 \(x\),从高位到低位遍历二进制位。

如果该位没有 \(1\) 就跳过,否则查看这位有没有代表元 \(p_i\),如果没有就把这个数设置为这一位的代表元。如果有了,就令 \(x\gets x\operatorname{xor} p_i\),然后继续往后遍历。

对于 \(\min,\max\) 和能否被表示都是简单的。

现在考虑排名之类的问题。需要重构线性基。

`

void rebuild(){
	cnt=0; memcpy(q,p,sizeof(p));
	for(int i=60;i>=0;i--)
		for(int j=i-1;j>=0;j--)
			if((p[i]>>j)&1) q[i]^=q[j];
	for(int i=0;i<=60;i++) 
		if(p[i]) d[++cnt]=q[i];
}

`

就是把各位独立。

CF1100F Ivan and Burgers

区间线性基模板题。

对于每一个前缀 \(r\) 建立前缀线性基,贪心地保留影响该位的最大的 \(l\) 即可。

注意更换之后原先的可以拿过去更新后面。

CF1902F Trees and XOR Queries Again

思想同上一题。维护最深的点,然后合并两个线性基即可,要求是所选的点深度必须 \(\ge dep_{\operatorname{lca(x,y)}}\)

P11713 [清华集训 2014] 玛里苟斯

首先,第一步观察就是你可以直接将 \(S\) 替换为 \(S\) 的线性基。虽然不改变能异或出来的数,但是会不会影响方案数导致期望变了?其实是不会的,设线性基大小为 \(\rm dim(V)\),因为线性基内部的元素可以支配最后的异或值,所以任何一个能被表示出来的数,其在线性基外面每个数都可以随便选或者不选,方案数为 \(2^{n-\rm dim(V)}\) 都是相同的,线性基内部每个数是否被选择就就唯一确定了,方案数为 \(1\)。故每个数方案数相同,直接换成线性基之后还是方案数相同。

于是我们要求的就是线性基中所有能被表示出来的 \(x\),对其 \(x^k\) 之后求平均值。将 \(x\) 进行二进制拆分,\(x=\sum\limits_{i=0}^{\log x}b_i2^i\),其中 \(b_i\in \{0,1\}\)\((\sum\limits_{i=0}^{\log x}b_i2^i)^k\) 的组合意义就是从所有二进制位中可重复地选择 \(k\) 个二进制位,把他们的大小相乘之后对于所有方案求和。

直接暴力枚举选择哪 \(k\) 个的复杂度是 \(\log^k V\),可以接受。问题是我们现在手头上并没有具体的线性基能表示出来的数字的集合,一共有 \(2^{\rm dim(V)}\) 种数也不可能全部都枚举出来,这个量非常大。

于是我们先枚举这 \(k\) 个二进制位求出乘积之后算有多少种从线性基中选择数的方案使得其可以包含这 \(k\) 个二进制位。然后用乘积乘以方案数累加进答案。由于是期望所以最后要乘以 \(\dfrac{1}{2^{\rm dim(V)}}\)

为了包含这 \(k\) 个二进制位,我们再次对于这 \(k\) 个二进制位(离散化为 \([0,k-1]\))建立线性基来求方案数。设新的线性基大小为 \(\dim(V')\),那么最后包含这 \(k\) 个二进制位的方案数就是 \(2^{\rm dim(V)-\rm dim(V')}\),除以 \(\rm dim(V)\) 之后,贡献系数就是 \(2^{-\rm dim(V')}\)。最后乘上 \(k\) 个二进制位的乘积即可。

还有一个问题就是精度不会爆掉吗?可以发现唯一出现小数的地方是 \(2^{-\rm dim(V')}\) 这个地方,假设选择的 \(k\) 个二进制位中不同的位子的个数为 \(m\)。那么 \({\rm dim}(V')\le m\),一个进制位 \(i\) 会贡献 \(2^i\),所以除非 \(i=0\),否则绝大部分情况都是会至少抵消甚至贡献更多的 \(2\)。只有当 \(m=1\)\(i=0\) 或者 \(m=2,i\in \{0,1\}\) 的时候才会出现 \(\dfrac{1}{2}\) 的系数,这个好处理,我们先给答案乘以 \(2\),最后再判断奇偶性看看是否需要加上 \(0.5\) 即可。

时间复杂度为 \(O(k\log^{k+1} V)\)

CF1336E2 Chiori and Doll Picking

LGV 引理

杂题

CF1603F October 18, 2017

posted @ 2024-06-08 17:04  Mirasycle  阅读(46)  评论(0)    收藏  举报