Linear Algebra in Competitive Programming
1. Basis
线性基 (v1,v2,...,vn)∈Rn(v_1,v_2,...,v_n)\in\R^n(v1,v2,...,vn)∈Rn 线性无关。
Properties
1.
由 kkk 维线性基组成的线性空间的大小为 2k2^k2k。
2.
存在一种最简表示,使得每个 bit 之间无交,但每个 bit 的二进制表示不一定只有一位是 1。
Template
template<typename T> struct XORBasis {int bit_size, size;std::vector<int> bit;// bool good_pos;void resize(int _bit_size) {size = 0;// good_pos = 1;bit_size = _bit_size;bit.resize(bit_size);}XORBasis(int _bit_size) {resize(_bit_size);}~XORBasis() {std::vector<int>().swap(bit);}// void refresh() {// for (int i = bit_size - 1; i >= 0; i--) {// for (int j = i - 1; j >= 0; j--) {// if (bit[i] >> j & 1) {// bit[i] ^= bit[j];// }// }// }// good_pos = 1;// }bool insert(T x, int index) {for (int i = bit_size - 1; i >= 0; i--) {if ((x >> i) & 1) {if (!bit[i]) {bit[i] = x;size++;// good_pos = 0;return true;} else {x ^= bit[i];}} else {continue;}}return false;}T get_kth(T k) {assert(k >= 0 && k <= (1ll << size));if (k == 0) return T(-1);if (k == 1) return T(0);T res = T(0);T cnt = (1ll << size);for (int i = bit_size - 1; i >= 0; i--) {if (bit[i]) {cnt >>= 1;if (k > cnt) {if (!(res >> i & 1)) {res ^= bit[i];}k -= cnt;} else {if (res >> i & 1) {res ^= bit[i];}}}}return res;// if (good_pos == 0) {// refresh();// }// k--;// T res = T(0);// for (int i = 0; i < bit_size; i++) {// if (!bit[i]) {// continue;// }// if (k & 1) {// res ^= bit[i];// }// k >>= 1;// }// return res;}T lower_bound(T x) {if (x < 0) {return T(0);}T res = T(0);T cnt = T(1ll << size);T mask = T(0);for (int i = bit_size - 1; i >= 0; i--) {if (bit[i]) {cnt >>= 1;if ((x >> i) & 1) {res += cnt;if (!(mask >> i & 1)) {mask ^= bit[i];}} else {if (mask >> i & 1) {mask ^= bit[i];}}} else {if ((x ^ mask) >> i & 1) {if (x >> i & 1) {return res + cnt + 1;} else {return res + 1;}}}}return res + 1;}// T get_rank(T x) {// if (x < 0) {// return T(0);// }// if (good_pos == 0) {// refresh();// }// T res = T(0), now = T(x), base = T(1ll << (size - 1));// for (int i = bit_size - 1; i >= 0; i--) {// if (!bit[i]) {// continue;// }// if ((now >> i) & 1) {// res += base;// now ^= bit[i];// }// base >>= 1;// }// return res + 1;// }
};
Problems
1. CF2143F
题意
给一个序列 a1,a2,...,ana_1,a_2,...,a_na1,a2,...,an,若干次询问,每次问一个区间 a[l,..,r]a[l,..,r]a[l,..,r],是否能进行任意有限次操作使得其严格增,一次操作为任取 l≤i≤j≤r,aj←aj⊕ail\le i\le j\le r,a_j\gets a_j\oplus a_il≤i≤j≤r,aj←aj⊕ai。
n≤2e5,a≤220n\le2e5,a\le 2^{20}n≤2e5,a≤220
做法
发现固定左端点,答案有单调性,考虑确定最大可能的右端点,一个数的变化只能由它及其左侧的元素的某些的异或和造成,考虑使用异或线性基考虑这个问题。固定左端点后,右侧有至多有 202020 个点会造成基维度增加,这些关键位置之间能形成的数的可能性不变,考虑分这 202020 段计算,重点在从一段到下一段时之前的最后一项在下一段的所有可能性中的大小位置,可以通过维护异或线性空间第 kkk 小以及一个数在线性空间中的排位计算。
代码
cf