运算律
- 与或异或分别满足交换律和结合律,但有两种同时出现时好像就都不满足了。
异或
-
异或的逆运算是它本身(参看各种解怪题选择性报告中树上异或路径)。
-
从这一性质出发,可以有一个推论:如果只考虑异或路径长度,那么图上的许多边是等价的。
-
譬如异或边生成树问题,使用类 Kruskal 算法(这里指逐渐加边的过程,并不贪心):
-
考虑 \(A,B\) 两个局部生成树,不妨设它们的根分别为 \(rt_A,rt_B\)。
-
则 \(u\in A\to v\in B(x)\) 这条边等价于 \(rt_A\to rt_B(x\oplus dis_{A,u}\oplus dis_{B,v})\) 这条边,两者本质相同。参看线段树分治一节中的 \(\text{CF938G Shortest Path Queries}\)。
-
-
另一个推论:异或最短/最长路可以由环长的线性基+任意简单路径的长求得。
- 参看 \(\text{P4151 [WC2011] 最大XOR和路径}\)。鉴于我现在不是来整理这个的而且我觉得位运算的东西太少不够写一篇,所以这些先鸽在这里。
异或线性基
-
定义集合 \(B\) 为集合 \(S\) 的线性基,当且仅当:
-
\(\forall S_i=\operatorname{xorsum}(T),T\subseteq B\),其中 \(T\) 为 \(B\) 的子集。即 \(S\) 中任意元素都可用 \(B\) 的某个子集的和表示出。
-
\(\nexists\ B_i=\operatorname{xorsum}(T),T\subseteq B,B_i\notin T\)。即 \(B\) 是极小的,不存在一个 \(B_i\) 能被不通过它本身的方式用 \(B\) 的某个子集表示出。
-
-
从而其有如下性质:
-
\(\nexists\ T\subset B,\forall S_i=\operatorname{xorsum}(T)\)。过于显然,证明略。
-
\(S_i\) 在 \(B\) 中对应的 \(T\) 唯一。不会证。
-
就本质来讲,\(B\) 与 \(S\) 等价,即 \(S\) 中元素(加权)可构造出的元素,都可以用 \(B\) 中元素等效构造。
-
-
构造:在线。
-
线性基的构造方法不唯一,但我们这里介绍一种好想好写且便于按位贪的:
-
首先容易证明,线性基的长度(元素个数)不超过 \(S\) 的二进制位最多的元素的位数。事实上,在异或运算下,二进制的各位是互相独立的向量元素。
-
从而我们规定:
-
如果 \(a_i\) 存在,那么只有 \(a_i\) 的第 \(i\) 位为 \(1\)。
-
如果 \(a_i\) 不存在,那么只有 \(a_j(j>i)\) 的第 \(i\) 位可能为 \(1\)。
-
-
-
首先构建一个空线性基,接着不断向其中插入 \(S_i\)。
-
对于每个 \(S_i\),在二进制意义下从高向低位枚举。
-
若该位为 \(0\),跳过。
-
若该位为 \(1\):当 \(\exists\ a_i\),\(S_i=S_i\bigoplus a_i\);否则,将 \(S_i\) 插入为 \(a_i\)。
-
-
插入操作:
-
首先对于 \(j<i\),若 \(S_i\) 该位为 \(1\),\(S_i=S_i\bigoplus a_j\)。本操作完毕后的 \(S_i\) 即为 \(a_i\)。
-
然后对于 \(j>i\),若 \(a_j\) 的第 \(i\) 位为 \(1\),\(a_j=a_j\bigoplus a_i\)。
-
-
取最值操作(取 \(S_x\oplus v\) 的最大/最小值):
-
自高向低遍历每一位,若 \(a_i\oplus v>/<v\),则 \(v=v\oplus a_i\)。
-
这就是我们的规定的意义:若不等号成立,说明是通过变换这一位的值达到此效果,即按位贪这一位,不管低位。
-
看起来似乎会有点疑惑,这样似乎会把每一位都贪上;不过我们考察实际意义,发现 \(a_i\) 存在的时候这一位上才会进行贪心,而这一位存在恰恰意味着其他 \(a\) 的第 \(i\) 位均为 \(0\),故这一位上构造什么我们是随心所欲的。
-
换言之,\(a_i\) 的存在就代表着我们对第 \(i\) 位的掌控;故优先考虑掌控高位,故规定先放高位,忽略低位。
-
-
正确性:
-
异或运算的逆运算是它本身,所以我们在插入过程中做的一系列操作都是可逆的。
-
从而相当于我们把 \(S\) 放了进去。
-
-
合并:容易想到,只要将一个插进另一个就好。可以启发式合并。
-
struct linear_basis{
ll a[61];
il void ins(ll x){
foR(i,60,0)
if(x&(1ll<<i)){
if(!a[i]){
foR(j,i-1,0)
if(x&(1ll<<j))
x^=a[j];
a[i]=x;
For(j,i+1,60)
if(a[j]&(1ll<<i))
a[j]^=x;
break;
}
else x^=a[i];
}
}
};
P4151 [WC2011] 最大XOR和路径
-
注意到任何一条路径都可以表示为简单路径上挂了很多个环。
-
既然连通,则每个环都能走到;要往返,故到环的路径无贡献;不同的简单路径之间构成环,选一个不同简单路径构成的环相当于更换简单路径。
-
于是随便选一条简单路径,在环构成的线性基里贪一下就行了。
广义线性基
-
考虑把上面的运算推广到任意运算,单个数字推广到高维向量。
-
其实一样,因为观察可以发现上面的构造过程本质上是个在线高消!