正交线性基。
参考 link。
orz Sooke。
线性基
回忆一下线性基,Z2n 上的一组线性无关的基。
Z2n 上的基本运算:
加法:不进位加法,就是异或。
点积:参考向量,a×b=popcount(a&b)mod2 。
回忆一下 FWT 的过程,会发现 [xu]F→[xv]F^ 的转移矩阵系数为 (−1)u×v。
正交线性基
a×b=0 则称 a,b 正交,记作 a⊥b,因为几何意义上是两向量垂直。
对于一 Z2n 的线性子空间 A,定义其正交补为 {x∣∀y∈A,x⊥y}。
首先如果 a⊥x,b⊥x,那么 (a+b)⊥x,这个可以分配律简单证。
因此正交补也可以找到一组基来表示,考虑一下基的大小,设原线性基大小为 k,以这 k 个为基底,那么容易发现有 n−k 维无关,因此正交补大小为 2n−k。
考虑咋求,先把线性基消成最简,然后要和每个垂直,因此用原线性基空的行来放,然后如果和线性基中的有交就补上一个使得点积为 0 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
for (int i = n - 1; i >= 0; i--) { for (int j = i - 1; j >= 0; j--) { if (A[i] >> j & 1) { A[i] ^= A[j]; } } } for (int i = n - 1; i >= 0; i--) { if (A[i] == 0) { B[i] = 1 << i; for (int j = n - 1; j > i; j--) { if (A[j] >> i & 1) { B[i] |= 1 << j; } } } }
|
时间复杂度 O(n2) 。
记 A 的正交线性基为 A⊥。
线性基 FWT
挺秒的一个东西。
注意到线性基满足加法封闭,令 ∗ 为异或卷积,× 为点乘,A^ 为 A FWT 后的结果,那么:
A∗A=A×2kA^×A^=A^×2k
因此 [xu]A^={0,2k}。
又由于 [xu]A^=∑(−1)u×v[xv]A,那么 ∀u×v=0,{u∣[xu]A^=2k}=A⊥,也就是正交补就是 A FWT 后的结果。
线性基求交
已知线性子空间 V1,V2 的基 A1,A2,求 V1∩V2 的基。
不用正交补的做法没有看懂qwq,感觉太引荐。
注意到令 F1=∑[u∈V1]xu,F2 同理,那么交可以用 F1×F2 来表示。
而 V1∪V2 可以用 V1∗V2 表示,而并是好求的,直接加入即可。
而上面线性基 FWT 正表示出了一种点乘和卷积之间的关系,令 V3 表示 V1∩V2,注意下面的运算中,系数只区别是否是 0 而不关系其具体值。
V3=V1×V2V3⊥=V1⊥∗V2⊥V3=(V1⊥∗V2⊥)⊥
可以这样做是因为正交补有可逆性。
因此求交复杂度也 O(n2) 。
一般实现时如果需要卡常,如果是询问一个数是否能被 A 表出,那么可以直接判断其是否与 A⊥ 中每个元素正交即可,因为该关系可逆。
已知 n 个 [0,2m−1] 的数,对于每个 0≤i≤m,求所有能异或表出的数中,popcount=i 的有几个。
m≤53 。
线性基大小如果 ≤m/2,那么直接暴力。
否则考虑线性基可以通过其正交补 FWT 得到,而正交补大小是 m−k,可以暴力求出。
接下来只要做 FWT,然后把 2m−k 的系数除掉就可以。
由于 FWT 的系数只和 u&v 有关,因此只需要记录正交补中每个数的 popcount,就可以简单统计对每个 i 的贡献了。
复杂度 O(n+2m/2) 。