线性基模板


AcWing 3164. 线性基
由高到低枚举二进制的每一位
通过高斯消元化为上三角矩阵
后将所有元素异或即可

#include 
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N];
signed main() {
    cin >> n;
    for (int i = 0; i < n; i ++ )  cin >> a[i];
    int k = 0;
    for (int i = 62; i >= 0; i -- ) {
        for (int j = k; j < n; j ++ ) {
            if (a[j] >> i & 1) {
                swap(a[j], a[k]);
                break;
            }
        }
        if (!(a[k] >> i & 1))   continue;
        for (int j = 0; j < n; j ++ )
            if (j != k && (a[j] >> i & 1))
                a[j] ^= a[k];
        k ++;
        if (k == n) break;
    }
    int res = 0;
    for (int i = 0; i < k; i ++ )   res ^= a[i];
    cout << res << endl;
    return 0;
}

AcWing 210. 异或运算
本题是上面一题的扩展,需要求第\(k\)小的数
先计算线性基
将得到的x个线性基的基底看作二进制的每一位,得到k的二进制表示
(注意判断得到的线性基是线性相关的还是线性无关的)

#include 
#define int long long
using namespace std;
const int N = 1e5 + 10;
int T, n, m;
int a[N];
signed main() {
    scanf("%lld", &T);
    for (int o = 1; o <= T; o ++ ) {
        scanf("%lld", &n);
        for (int i = 0; i < n; i ++ )  scanf("%lld", &a[i]);
        int k = 0;
        for (int i = 62; i >= 0; i -- ) {
            for (int j = k; j < n; j ++ ) {
                if (a[j] >> i & 1) {
                    swap(a[j], a[k]);
                    break;
                }
            }
            if (!(a[k] >> i & 1)) continue;
            for (int j = 0; j < n; j ++ ) 
                if (j != k && (a[j] >> i & 1))
                    a[j] ^= a[k];
            k ++;
            if (k == n) break;
        }
        reverse(a, a + k);
        printf("Case #%d:\n", o);
        scanf("%lld", &m);
        while (m -- ) {
            int x;
            scanf("%lld", &x);
            if (k < n) x --;
            if (x >= (1LL << k)) puts("-1");
            else {
                int res = 0;
                for(int i = 0; i < k; i ++ )
                    if (x >> i & 1)
                        res ^= a[i];
                printf("%lld\n", res);
            }
        }
    }
    return 0;
}