数论-线性基
线性基基基基基
求 \(k\) 小异或的高斯消元方法不是很懂,可能暂时也没功夫去学了,先来一发可以感性理解的线性基板子。
从高位到低位贪心。
性质:
- 基向量 \(p_i\) 的第 \(i\) 位是 \(1\) ,且是最高位。
- 用基向量构造其他向量的方法唯一。
- 无法构造 0 。
求向量组 \(a\) 的线性基 \(p\)
for (int i = 1; i <= N; ++i) {
for (int j = 62; j >= 0; --j)
if ((A[i]) >> j) & 1) {
if (!P[j]) {
P[j] = A[i];
break;
}
A[i] ^= P[j];
}
}
求最大值
int mx = 0;
for (int i = 62; i >= 0; --i)
if ((mx ^ P[i]) > mx)
mx ^= P[i];
求最小值
就是 \(p_0\) 。
第 \(k\) 小异或值
构造只有 \(p_i\) 的第 \(i\) 位为 \(1\) 的线性基。据说如果新的线性基大小(非 \(0\) 向量个数)等于原线性基,则仍然无法构造 \(0\) ,否则可以。
for (int i = 62; i >= 0; --i) {
for (int j = i - 1; j >= 0; --j)
if ((P[i] >> j) & 1)
P[i] ^= P[j];
}
int x = -1;
for (int i = 0; i <= 62; ++i)
if (P[i])
P[++x] = P[i];
}
上面的构造完成之后,就可以求 \(a\) 的第 \(k\) 小异或值了。
for (int i = 62; i >= 0; --i)
if ((k >> i) & 1)
ans ^= P[i];
判断向量是否能被构造
for (int i = 62; i >= 0; --i)
if ((x >> i) & 1)
x ^= P[i];
if (!x)
suc = 1;