ll get_min(){ if (O) return0; for (int i = 0; i <= n; ++i) if (a[i]) return a[i]; }
ll get_min(ll v){ for (int i = n; ~i; --i) v = min(v, v ^ a[i]); return v; }
严格第 k 小子集异或值
注意到我们现在还是行阶梯,我们要进一步操作将其化成行最简形矩阵
化成行最简形之后第 $k$ 小就很明显了,因为每一个 $a[i]$ 都对应了二进制的第 $i$ 位
注意要特判 $0$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
voidwork(){ for (int i = 0; i <= n; ++i) for (int j = 0; j < i; ++j) if (a[i] >> j & 1) a[i] ^= a[j]; } //先化为行最简形
ll get_kth(ll k){ ll ans = 0; k -= O; for (int i = 0; i <= n; ++i) { if (!a[i]) continue; if (k & 1) ans ^= a[i]; k >>= 1; } if (k > 0) return-1; elsereturn ans; }
判断 x 是否存在于线性基中
我们直接使用插入的方法,判断最后 $x$ 是否为 $0$ 即可
1 2 3 4 5 6 7 8
boolcheck(ll v){ for (int i = n; ~i; --i) { if (!(v >> i & 1)) continue; if (!a[i]) return0; v ^= a[i]; } return1; }
structLinearBasis { staticconstint n = 60; bool O; ll a[n + 1]; int cnt;
voidclear(){ O = 0; cnt = 0; for (int i = 0; i <= n; ++i) a[i] = 0; } voidinsert(ll v){ for (int i = n; ~i; --i) { if (!(v >> i & 1)) continue; if (!a[i]) { a[i] = v; break; } v ^= a[i]; } O |= !v; } voidwork(){ for (int i = 0; i <= n; cnt += a[i++] > 0) for (int j = 0; j < i; ++j) if (a[i] >> j & 1) a[i] ^= a[j]; } ll get_max(ll v = 0){ for (int i = n; ~i; --i) v = max(v, v ^ a[i]); return v; } ll get_min(){ if (O) return0; for (int i = 0; i <= n; ++i) if (a[i]) return a[i]; } ll get_min(ll v){ for (int i = n; ~i; --i) v = min(v, v ^ a[i]); return v; } ll get_kth(ll k){ ll ans = 0; k -= O; for (int i = 0; i <= n; ++i) { if (!a[i]) continue; if (k & 1) ans ^= a[i]; k >>= 1; } if (k > 0) return-1; elsereturn ans; } boolcheck(ll v){ for (int i = n; ~i; --i) { if (!(v >> i & 1)) continue; if (!a[i]) return0; v ^= a[i]; } return1; } } S;
区间线性基
我们注意到平时写的一般的线性基在插入的时候,$a[i]$ 所存储的值总是最靠左的那个
现在我们考虑维护每一个前缀线性基,但是 $a[i]$ 存储的值是最靠右的那一个
我们只需要对 $insert$ 稍做修改即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
structLinearBasis { staticconstint n = 30; int a[n + 1], p[n + 1];
voidinsert(int k, int v){ for (int i = n; ~i; --i) { if (!(v >> i & 1)) continue; if (!a[i]) { a[i] = v; p[i] = k; break; } if (k > p[i]) swap(a[i], v), swap(p[i], k); v ^= a[i]; } } intget_max(int k){ int v = 0; for (int i = n; ~i; --i) if (p[i] >= k) v = max(v, v ^ a[i]); return v; } } S;