古典叙事 · 技术札记

序章

山河有卷
人间有声

写代码,也写长风、旧城与未熄的灯。
愿每一篇随笔,都有自己的山水与回声。
阅览随笔

线性基

线性基

线性基可以理解为:用尽量少的一组数,表示原集合所有“子集异或和”。

1. 核心思想

把一个整数看成二进制向量,例如:
3 = 011
5 = 101
6 = 110
异或相当于二进制向量的“加法”:
3 ^ 5 = 6
所以 {3, 5, 6} 里,6 是多余的,因为它能由 3 ^ 5 表示。
线性基会保留 {3, 5},丢掉 6。

2. 线性基维护什么

令 b[i] 表示:最高位是第 i 位的一个基向量。
插入一个数 x 时,从高位往低位消元:
若 x 的第 i 位是 0,跳过;
若 b[i] 不存在,把 x 放进 b[i];
若 b[i] 存在,令 x ^= b[i],消掉这一位;
最后若 x == 0,说明它可以由已有基表示,是冗余数。
例如插入 3, 5, 6:
3 = 011 -> b[1] = 3
5 = 101 -> b[2] = 5
6 = 110
6 ^ 5 = 011
3 ^ 3 = 000 -> 6 冗余

常用模板

#include <bits/stdc++.h>
using namespace std;

struct LinearBasis {
    static constexpr int LOG = 62; // long long 最高到 62 位
    long long b[LOG + 1]{};

    // 插入一个数
    bool insert(long long x) {
        for (int i = LOG; i >= 0; --i) {
            if (((x >> i) & 1LL) == 0) continue;

            if (!b[i]) {
                b[i] = x;
                return true; // 插入成功,线性基维数 +1
            }

            x ^= b[i];
        }
        return false; // x 可由已有基表示
    }

    // 所有子集异或和中的最大值
    long long getMax() const {
        long long ans = 0;
        for (int i = LOG; i >= 0; --i) {
            if ((ans ^ b[i]) > ans) {
                ans ^= b[i];
            }
        }
        return ans;
    }

    // 判断 x 能否由原集合某些数异或得到
    bool canRepresent(long long x) const {
        for (int i = LOG; i >= 0; --i) {
            if (((x >> i) & 1LL) == 0) continue;
            if (!b[i]) return false;
            x ^= b[i];
        }
        return true;
    }
};

int main() {
    LinearBasis lb;

    lb.insert(3);
    lb.insert(5);
    lb.insert(6);

    cout << lb.getMax() << '\n';          // 6
    cout << lb.canRepresent(6) << '\n';   // 1
    cout << lb.canRepresent(7) << '\n';   // 0
}

4. 它能解决什么题

题目描述 线性基操作
选若干数,使异或和最大 getMax()
某个值能否由若干数异或得到 canRepresent(x)
求不同子集异或和数量 若秩为 rank,数量是 2^rank
多组数合并 把一个线性基里的每个 b[i] 插入另一个
第 k 小 / 第 k 大子集异或和 需要把线性基进一步化为简化行阶梯形

复杂度很低:一次插入、查询都是 O(LOG),对 long long 来说约 O(63)。

posted @ 2026-07-22 17:34  Morphis‘  阅读(5)  评论(0)    收藏  举报

特别策划 · CINEMATIC NOTES

风沙与孤骑

风起塞外,
胜负在刀剑之前。

“把复杂拆成秩序,把未知写成答案。”
Morphis · 山河一卷 愿你从这里出发,仍能听见山风。 影像:farfarSébastien Goldberg / Unsplash