Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .verify-helper/timestamps.remote.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"tests/library_checker_aizu_tests/handmade_tests/seg_tree_find.test.cpp": "2026-01-23 04:31:29 +0000",
"tests/library_checker_aizu_tests/handmade_tests/seg_tree_find_small.test.cpp": "2026-01-23 04:31:29 +0000",
"tests/library_checker_aizu_tests/handmade_tests/seg_tree_midpoint.test.cpp": "2026-02-27 11:16:07 -0700",
"tests/library_checker_aizu_tests/handmade_tests/xor_basis_walk.test.cpp": "2026-03-08 13:19:49 -0600",
"tests/library_checker_aizu_tests/loops/chooses.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/loops/quotients.test.cpp": "2024-11-17 14:04:03 -0600",
"tests/library_checker_aizu_tests/loops/submasks.test.cpp": "2025-02-10 14:50:36 -0700",
Expand All @@ -106,7 +107,6 @@
"tests/library_checker_aizu_tests/math/solve_linear_mod.test.cpp": "2025-09-07 16:12:35 -0600",
"tests/library_checker_aizu_tests/math/tetration.test.cpp": "2024-11-17 14:04:03 -0600",
"tests/library_checker_aizu_tests/math/totient.test.cpp": "2024-11-17 14:04:03 -0600",
"tests/library_checker_aizu_tests/math/xor_basis_intersection.test.cpp": "2026-03-06 16:39:24 -0700",
"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_binary_tree.test.cpp": "2025-02-10 14:50:36 -0700",
"tests/library_checker_aizu_tests/monotonic_stack_related/cartesian_k_ary_tree.test.cpp": "2026-01-18 11:15:41 +0000",
"tests/library_checker_aizu_tests/monotonic_stack_related/count_rectangles.test.cpp": "2026-01-18 11:15:41 +0000",
Expand Down
6 changes: 6 additions & 0 deletions library/math/matrix_related/walk.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bitset<B> walk(bitset<B>& k) {
bitset<B> res;
for (int i = B, j = npivot; i--;)
if (basis[i][i] && res[i] ^ k[--j]) res ^= basis[i];
return res;
}
28 changes: 14 additions & 14 deletions library/math/matrix_related/xor_basis_ordered.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@
//! basis_ordered<int> b1;
//! basis_ordered<ll> b2;
//! basis_ordered<bitset<lg>> b3;
//! b2.insert(x); // 0 <= x < (1LL<<lg)
//! b2.insert(x); // 0 <= x < (1LL<<B)
//! @endcode
//! @time O(lg)
//! @space O(lg)
const int lg = 60;
template<class T> struct basis_ordered {
int siz = 0;
T b[lg]{};
int shrink(T& v) {
for (int i = lg - 1; i >= 0; i--)
if (((v >> i) & T(1)) != T(0)) {
if (b[i] == T(0)) return i;
v ^= b[i];
//! @time O(q * B^2/32)
//! @space O(B^2/32)
template<int B> struct xor_basis {
bitset<B> basis[B];
int npivot = 0, nfree = 0;
int shrink(bitset<B>& v) {
for (int i = B; i--;)
if (v[i]) {
if (!basis[i][i]) return i;
v ^= basis[i];
}
return -1;
}
bool insert(T v) {
bool insert(bitset<B>& v) {
int i = shrink(v);
return i >= 0 ? b[i] = v, ++siz : 0;
return i >= 0 ? basis[i] = v, ++npivot : !++nfree;
}
#include "walk.hpp"
};
1 change: 0 additions & 1 deletion tests/.config/.cppcheck_suppression_list
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,3 @@ unusedFunction:../kactl/stress-tests/utilities/genTree.h:49
containerOutOfBounds:../library/data_structures_[l,r)/uncommon/permutation_tree.hpp:85
ctuOneDefinitionRuleViolation:../library/data_structures_[l,r)/bit.hpp:5
ctuOneDefinitionRuleViolation:../library/data_structures_[l,r)/lazy_seg_tree.hpp:4
shiftTooManyBits:../library/math/matrix_related/xor_basis_ordered.hpp:18
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#define PROBLEM \
"https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A"
#include "../template.hpp"
#include "../../../library/contest/random.hpp"
#include "../../../library/math/matrix_related/xor_basis_ordered.hpp"
const int B = 18;
vector<bitset<B>> get_all(const vector<bitset<B>>& basis) {
int n = ssize(basis);
vector<bitset<B>> span;
for (int mask = 0; mask < (1 << n); mask++) {
bitset<B> curr_xor;
assert(curr_xor.none());
for (int bit = 0; bit < n; bit++)
if ((mask >> bit) & 1) curr_xor ^= basis[bit];
span.push_back(curr_xor);
}
ranges::sort(span, {}, [&](const bitset<B>& x) -> long {
return x.to_ulong();
});
return span;
}
int main() {
cin.tie(0)->sync_with_stdio(0);
for (int num_tests = 0; num_tests < 1000; num_tests++) {
xor_basis<B> b;
int n = rnd(1, 18);
vector<bitset<B>> naive_basis;
for (int i = 0; i < n; i++) {
bitset<B> val = rnd(0, (1 << n) - 1);
if (b.insert(val)) naive_basis.push_back(val);
assert(b.npivot + b.nfree == i + 1);
}
assert(ssize(naive_basis) == b.npivot);
vector<bitset<B>> fast_basis;
for (int i = 0; i < B; i++)
if (b.basis[i][i]) fast_basis.push_back(b.basis[i]);
vector<bitset<B>> naive_span = get_all(naive_basis);
vector<bitset<B>> fast_span = get_all(fast_basis);
assert(naive_span == fast_span);
for (int i = 0; i < ssize(naive_span); i++) {
bitset<B> k = i;
assert(naive_span[i] == b.walk(k));
}
}
cout << "Hello World\n";
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,16 @@ void check_condition_unordered(const basis& b) {
or_bits |= b.b[i];
}
}
void check_condition_ordered(
const basis_ordered<ll>& basis3,
const basis_ordered<bitset<lg>>& basis4) {
ll or_bits3 = 0;
bitset<lg> or_bits4 = 0;
for (int i = 0; i < lg; i++) {
assert(basis3.b[i] == 0 ||
bit_floor(1ULL * basis3.b[i]) == (1ULL << i));
assert(
(bit_floor(uint64_t(basis3.b[i])) & or_bits3) == 0);
assert((bit_floor(uint64_t(basis4.b[i].to_ullong())) &
or_bits4.to_ullong()) == 0);
or_bits3 |= basis3.b[i];
or_bits4 |= basis4.b[i];
const int B = 30;
void check_condition_ordered(const xor_basis<B>& basis2) {
bitset<B> or_bits2;
for (int i = 0; i < B; i++) {
assert(basis2.basis[i].none() ||
bit_floor(basis2.basis[i].to_ulong()) ==
(1ULL << i));
assert((bit_floor(basis2.basis[i].to_ulong()) &
or_bits2.to_ulong()) == 0);
or_bits2 |= basis2.basis[i];
}
}
int main() {
Expand All @@ -38,43 +34,36 @@ int main() {
int n;
cin >> n;
basis basis1;
basis_ordered<int> basis2; // to check that it compiles
assert(
sz(basis2.b) == lg); // remove unused var warning
basis_ordered<ll> basis3;
basis_ordered<bitset<lg>> basis4;
xor_basis<B> basis2;
for (int i = 0; i < B; i++)
assert(basis2.basis[i].none());
for (int i = 0; i < n; i++) {
int val;
cin >> val;
bitset<B> v = val;
assert(basis1.insert(val));
assert(!basis1.insert(val));
assert(basis3.insert(val));
assert(!basis3.insert(val));
assert(basis4.insert(val));
assert(!basis4.insert(val));
assert(basis2.insert(v));
assert(!basis2.insert(v));
}
check_condition_unordered(basis1);
check_condition_ordered(basis3, basis4);
check_condition_ordered(basis2);
int m;
cin >> m;
basis basis5;
basis_ordered<int> basis6;
assert(sz(basis6.b) == lg);
basis_ordered<ll> basis7;
basis_ordered<bitset<lg>> basis8;
basis basis3;
xor_basis<B> basis4;
for (int j = 0; j < m; j++) {
int val;
cin >> val;
assert(basis5.insert(val));
assert(!basis5.insert(val));
assert(basis7.insert(val));
assert(!basis7.insert(val));
assert(basis8.insert(val));
assert(!basis8.insert(val));
bitset<B> v = val;
assert(basis3.insert(val));
assert(!basis3.insert(val));
assert(basis4.insert(v));
assert(!basis4.insert(v));
}
check_condition_unordered(basis5);
check_condition_ordered(basis7, basis8);
basis inter = intersection(basis1, basis5);
check_condition_unordered(basis3);
check_condition_ordered(basis4);
basis inter = intersection(basis1, basis3);
check_condition_unordered(inter);
cout << sz(inter.b) << " ";
for (int val : inter.b) cout << val << " ";
Expand Down
Loading