学弟 linshey 在怒刷候选队互测 uoj#698 时提出了一个著名的问题:给定两组线性基 \(A=\{u_1,u_2,\cdots,u_a\},B=\{v_1,v_2,\cdots,v_b\}\),它们形成的线性空间的交怎么用一组线性基 \(C\) 表示呢?
仔细想想这个问题并不简单,因为如果简单地用 \(A\) 中所有能被 \(B\) 表示的基向量组出 \(C\) 的话是不对的,完全可能基向量不在 \(B\) 中但它们的线性组合在 \(B\) 中,如 \(A=\{5,3\},B=\{6\}\)。
那么可能可以考虑重构一下 \(A\),尽量用在交空间中的向量来表示 \(A\)。
如何找出一个非平凡的向量 \(w\) 使其在 \(A\cap B\) 中呢?我们不妨钦定 \(u_1\) 必选以避免 \(0\),那么尝试用剩余的所有向量即 \((A\setminus u_1)\cap B\) 来表示 \(u_1\)。如果表出来了令 \(w\) 为在 \(B\) 中的向量的异或和以代替 \(u_1\) 即可,否则包含 \(u_1\) 的向量都不在 \(B\) 中,删去 \(u_1\) 即可。
可以发现这样处理之后交空间不变且问题得到了简化,那么继续对 \(u_2,u_3,\cdots,u_a\) 进行这样的处理,剩下的向量组 \(A'=\{w_1,w_2,\cdots,w_{a'}\}\) 满足每个基向量都在 \(B\) 中,于是 \(A\cap B=A'\cap B=A'\),构建 \(A'\) 的线性基即为答案。
整个流程的复杂度瓶颈在于表示每个 \(u_i\) 时构建当前 \((A\setminus u_i)\cap B\) 的线性基。可以发现构建时 \(u_i\) 以前的向量都在 \(B\) 中从而不会产生贡献,我们只需构建 \(A_{i+1},\cdots,A_a\) 与 \(B\) 的并的线性基,而这可以通过后缀和处理。
那么整个算法过程就是:
构建辅助线性基 \(D=B\)。
按顺序考虑 \(i=a,a-1,\cdots,1\)
- 尝试用 \(D\) 表出 \(u_i\),若成功则取出 \(w=\) 所有在 \(B\) 中的向量的异或和 以更新 \(C\)。
- 用 \(u_i\) 更新 \(D\)(更新时保持原有基向量不变就可避免属于 \(B\) 的部分被修改)。
如果认为异或运算 \(O(1)\) 那么算法复杂度为 \(O(\log^2 A)\),其中 \(A\) 是值域,应该是比较优秀的。