二进制线性基学习笔记

二进制线性基学习笔记

定义

定义(性质型定义) 定义线性基为其中的元素可以通过求异或和,得到原集合的元素任意求异或和得到的所有值的集合,且集合大小最小。

性质

线性基大小定理 线性基的大小 \(\le \log a_i\)

我们把 \(a\) 的每一位取出来形成一个 \(n \times \log a_i\) 的矩阵。

线性基本质上是把这个矩阵看作系数矩阵后求出的简化阶梯矩阵。因为初始矩阵的各种组合对应了 \(a\) 的各种组合。且系数矩阵和简化阶梯矩阵等价。

于是线性基大小就是 \(\min(n, \log a_i) \le \log a_i\)

线性基子集非零定理 线性基不存在异或和为 \(0\) 的子集。

\(p_a \oplus p_b \oplus p_c \oplus p_x=0\),则 \(p_a \oplus p_b \oplus p_c=p_x\),遂 \(p_x\)​ 是多余的,与定义矛盾。

做法

贪心求法的正确性 设线性基数组为 \(d_i\) 则下列操作得到的 \(d\) 去除 \(0\) 后是线性基:

  • 对于每个 \(x\) 从高位到低位进行。
  • 如果 \(x\) 的第 \(i\) 位为1,判断 \(d_i\) 是否为 \(0\)。如果是,\(d_i=x\) 并退出;如果不是,\(x=x \oplus d_i\) 然后重复此步。

如果 \(x\)\(i\) 位为 \(1\)\(d_i\) 这一位为 \(1\),那么显然这一位用 \(d_i\) 结合其它的可以表示。否则,这一位不需要表示。由此,所有的数都可以被我们表示出来,得证。

由此我们也可以得知:若 \(d_i\) 不为 \(0\),则 \(d_i\) 的最高的 \(1\) 位在第 \(i\) 位。

void insert(int x)
{
    for(int i = 55;i >= 0;i--)
    {
        if((x >> i) & 1)
        {
            if(d[i]) x ^= d[i];
            else
            {
                d[i] = x;
                return;
            }
        }
    }
}

应用

应用 1 求异或和的最大值。

考虑直接贪心解决即可。

int ansmx()
{
	int ans = 0;
    for(int i = 55;i >= 0;i--) if((ans ^ d[i]) > ans) ans ^= d[i];
   	return ans;
}

应用 2 求异或和的最大值。

仿照最大值做即可。

int ansmn()
{
	int ans = (1ll << 55) - 1;
    for(int i = 55;i >= 0;i--) if((ans ^ d[i]) < ans) ans ^= d[i];
   	return ans;
}
posted @ 2025-02-21 23:34  邻补角-SSA  阅读(18)  评论(0)    收藏  举报