Skip to content

Commit 4fb15e5

Browse files
committed
fix: fixed some bugs in XORBasis.
1 parent 55b23e9 commit 4fb15e5

1 file changed

Lines changed: 22 additions & 14 deletions

File tree

src/alfred/math/linear.hpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ Matrix<T> power(Matrix<T> M, long long index) {
130130
template <class T>
131131
struct XORBasis {
132132
constexpr static T mx = std::numeric_limits<T>::max();
133-
constexpr static int C = std::__lg(mx);
133+
constexpr static int C = std::numeric_limits<T>::digits;
134134

135135
int siz = 0;
136136
std::array<T, C> p;
@@ -169,6 +169,7 @@ struct XORBasis {
169169
}
170170
}
171171
std::vector<T> narr;
172+
narr.reserve(siz);
172173
for (int i = 0; i < C; i++) {
173174
if (p[i] != 0) narr.push_back(p[i]);
174175
}
@@ -178,25 +179,32 @@ struct XORBasis {
178179
inline T kth(size_t k) { // kth minimum
179180
T ans = 0;
180181
assert(k >= 1);
181-
auto narr = rebuild();
182-
if (k > 1 || !has_zero) {
183-
k -= has_zero;
184-
assert(k < (1ull << siz));
185-
for (int i = siz - 1; i >= 0; i--) {
186-
if (k >> i & 1) ans ^= narr[i];
187-
}
182+
auto narr = rebuild(); // narr[0] = smallest by MSB; narr[i] corresponds to bit i in k's binary (LSB -> narr[0])
183+
if (has_zero) {
184+
if (k == 1) return 0;
185+
else --k;
186+
}
187+
assert(k < (1ull << siz));
188+
// map bit i of k to narr[i] (LSB -> narr[0])
189+
for (int i = 0; i < siz; i++) {
190+
if ((k >> i) & 1ULL) ans ^= narr[i];
188191
}
189192
return ans;
190193
}
191-
inline size_t rank(T x) {
194+
inline size_t rank(T x) const {
192195
size_t ans = 0;
193-
auto narr = rebuild();
194-
for (int i = siz - 1; i >= 0; i--) {
195-
if (x >= narr[i]) {
196-
ans |= 1ull << i, x ^= narr[i];
196+
auto narr = rebuild(); // narr ordered by increasing MSB
197+
for (int i = (int)narr.size() - 1; i >= 0; --i) {
198+
T b = narr[i];
199+
int hb = std::__lg(b);
200+
if (((x >> hb) & 1U) != 0) {
201+
x ^= b;
202+
ans |= (1ULL << i);
197203
}
198204
}
199-
return ans + has_zero;
205+
// after reduction, x should be 0 iff representable
206+
assert(x == 0 && "rank(x): x is not representable by this basis");
207+
return ans + (has_zero ? 1ULL : 0ULL); // 1-based
200208
}
201209
};
202210

0 commit comments

Comments
 (0)