线性基学习笔记

线性基具有的性质:

参见线性基学习笔记 - Menci

线性基插入和查询的写法

Menci Version

单次插入时间复杂度为 \(O(log^2 n)\)

单次查询时间复杂度为 \(O(log n)\)

const int MAXL = 60;

struct LinearBasis{
    long long a[MAXL + 1];
    LinearBasis(){std::fill(a, a + MAXL + 1, 0);}
    void insert(long long t){
        // 逆序枚举二进制位
        for (int j = MAXL; j >= 0; j--){
            // 如果 t 的第 j 位为 0,则跳过
            if (!(t & (1ll << j))) continue;
            // 如果 a[j] != 0,则用 a[j] 消去 t 的第 j 位上的 1
            if (a[j]) t ^= a[j];
            else{
                // 找到可以插入 a[j] 的位置
                // 用 a[0...j - 1] 消去 t 的第 [0, j) 位上的 1
                // 如果某一个 a[k] = 0 也无须担心,因为这时候第 k 位不存在于线性基中,不需要保证 t 的第 k 位为 0
                for (int k = 0; k < j; k++) if (t & (1ll << k)) t ^= a[k];
                // 用 t 消去 a[j + 1...L] 的第 j 位上的 1
                for (int k = j + 1; k <= MAXL; k++) if (a[k] & (1ll << j)) a[k] ^= t;
                // 插入到 a[j] 的位置上
                a[j] = t;
                // 不要忘记,结束插入过程
                return;
            }
            // 此时 t 的第 j 位为 0,继续寻找其最高位上的 1
        }
        // 如果没有插入到任何一个位置上,则表明 t 可以由 a 中若干个元素的异或和表示出,即 t 在 span(a) 中
    }
    long long queryMax()
    {
        long long res = 0;
        for (int i = 0; i <= MAXL; i++) res ^= a[i];
        return res;
    }
};
Another Version

单次插入时间复杂度 \(O(log n)\)

单次查询时间复杂度 \(O(log n)\)

typedef unsigned long long ull;
const int MAXL = 63;

ull p[MAXL + 5];

inline void ins(ull x){
    for(int i = MAXL; i + 1; -- i){
    	if((x >> i) & 1){
	        if(!p[i]){
	            p[i] = x;
	            return ;
	        }
	        x ^= p[i];
	    }
    }
    return ;
}
ull query(ull x) {
    ull res = x;
    for (int i = MAXL; i + 1; -- i)
        if((res ^ p[i]) > res)
            res ^= p[i];
    return res;
}

线性基合并

CF1100F Ivan and Burgers

你可能感兴趣的:(线性基学习笔记)