算法学习笔记(12): 线性基

算法,学习,笔记,线性 · 浏览次数 : 22

小编点评

**线性基** 线性基是一个包含所有可能线性组合的集合。线性基的定义如下: - 如果集合 S 中的任意元素 a 可以由集合 S 中的其他元素通过线性组合表示出来,则 S 是一个线性基。 - 线性基的维数等于线性基中线性无关的元素数量。 **异或运算是线性基中两个元素的线性组合** 设 a 和 b 是线性基中两个元素,它们的线性组合为 c,则: c = a ^ b **三点性质** 1. 如果集合 S 是线性基,则 S 的任意子集也是线性基。 2. 如果集合 S 是线性基,则线性基中任意三个线性无关元素线性无关。 3. 线性基的维数等于线性基中线性无关的元素数量。 **新增一个数查询异或和第 \\(k\\) 小查询异或和最大值** 1. 首先找到xxj内最大的数,即最高为 1 的位。 2. 如果 i < j,则 res = xxj[i],然后逆序 j 枚举 [0, i),如果,res 的第 j 位不为 1,那么res ^= xxj[j]。 3. 否则,就令 xxj[i] = x。 4. 最后,如果,最终 x 变成了 0,证明,用之前存在的数可以凑出 x,否则,不可以。

正文

线性基

熟练掌握异或运算是食用本文的大前提,请读者留意

是什么?

是一种利用线性代数的知识,用于解决异或问题的一种手段(不能算作数据结构吧这)

本文并不会涉及到线性代数。而是从OI基础算法思想的角度阐释线性基。尽管这可能违背了设计该方法的初衷。

一般来说,预处理的时间复杂度为 \(O(kn)\) 其中 \(k\) 一般为 \(31 \sim 32\),也就是 \(log_2max\)。单次操作一般也是 \(O(k)\) 的复杂度。

可以做什么?

  • 查询异或和第 \(k\)

  • 查询异或和最大值(最常用)

  • 某个数可否被异或出来

  • ……

三点性质

  • 线性基内任何几个非0的数异或起来都不可能为0

  • 原序列里面的任意一个数都可以由线性基内的几个数异或得来

  • 线性基内数个个数在序列一定的情况下一定,但是线性基内的值不一定

  • 数的个数在保证性质2的情况下是最少的,且不超过位长

如何实现?

xxj 是一个数组,至于为什么用这个名字……

xxj[i] 表示最高为 1 的位 i 的一个异或和(如果有的话)。

我们只需要维护这么 \(k\) 个数就行了

我们可以这么理解,0100 可以由 01010001 异或和起来,那么我们只需要维护 01010001 即可。

为什么可以保证性质2?

可以理解为贪心,一位一位的拼凑出任意一个数。

严谨的证明就需要用到更深层的知识了,这里不做说明

新增一个数

考虑如何新增一个数 x 进去?

由于我们维护的是异或和,那么对于 xxj 内的任何元素都可以异或上 x 以保证至多只有 \(k\) 个数。

假设 x 最高为 1 的位为 i,如果 xxj[i] 已经存在了一个数,那么我们将 x 异或上 xxj[i],重复上述步骤,否则,就令 xxj[i] = x

如果,最终 x 变成了 0,那么证明,用之前存在的数可以凑出 x,否则,不可以。

其实,这既是维护基的方法,也是判断某个数是否可以被异或出来的方法……

查询可以异或出来的最大值

这里,我们利用贪心的思想,先找到xxj内最大的数,也就是最高为 1 的为最高的那个数。

很明显,如果 i < j 那么 xxj[i] < xxj[j]

假如我们找到了 xxj[i],令 res = xxj[i],然后逆序 j 枚举 [0, i),如果,res 的第 j 位不为 1,那么res ^= xxj[j]

但是……我们的实现肯定不能如此复杂,那么就考虑贪心,如果 j 位为 变为了 1,那么之后的所有位都变为 1 做出的贡献都没有这个位做出的贡献大,那么我们优先保证最高位为1即可。

int qmax() {
    int ans = 0;
    for (int i = 30; i >= 0; --i) {
        ans = max(ans, ans ^ xxj[i]);
    }
    return ans;
 }   

解释了跟没解释一样……

查询异或和第 \(k\)

我们先解决 k = 1 的特殊情况。

显而易见,就是最小的 xxj[i] 了。

但是,如果数列的数的个数比线性基内的数的个数多,那么很明显,最小值为 0

那么特殊化一下。

其实就完全变化了

我们先将整个 xxj 数组处理一下。由大到小枚举 xxj[i]。对于个 xxj[i],我们尽量保证其二进制下1的个数最少。那么,可以保证线性基内的第 k 个数是第 2^(k-1) 大的。

二进制拆分一下,便是答案

#define marked(x, i) (((x)>>i)&1)
int prepare() {
    for (int i = 30; i >= 0; --i) {
        for (int j = i - 1; j >= 0; --j) {
            if (marked(xxj[i], j)) xxj[i] ^= xxj[j];
}


int kth(int k) {
    prepare();
    int res = 0;
    for (int i = 0; i < 30; ++i) {
        if (xxj[i]) {
            if (k & 1) res ^= xxj[i];
            k >>= 1;
        }
    }
    return res;
}

例题

模板题我们就不放了吧……

这是我们考试的一道题……至于为什么会与线性基扯上关系……我在题解中是这么写的

题解链接:2023-02-02 比赛试题及题解 - jeefies

所以,加油吧,勤奋学习的人们!

与算法学习笔记(12): 线性基相似的内容:

算法学习笔记(12): 线性基

# 线性基 > 熟练掌握异或运算是食用本文的大前提,请读者留意 [TOC] ## 是什么? 是一种利用线性代数的知识,用于解决异或问题的一种手段(不能算作数据结构吧这) > 本文并不会涉及到线性代数。而是从OI基础算法思想的角度阐释线性基。尽管这可能违背了设计该方法的初衷。 一般来说,预处理的时间复

算法学习笔记(28): 筛法

筛法 本文不作为教学向文章。 线性筛 线性筛是个好东西。一般来说,可以在 \(O(n)\) 内处理几乎所有的积性函数。 还可以 \(O(n)\) 找出所有的质数……(废话 杜教筛 放在偏序关系 \((\Z, |)\) 中卷积…… 如何快速的求 \(S(n) = \sum_{i = 1}^n f(i)

算法学习笔记(6): 树链剖分

树链剖分 树链剖分是一个很神奇,但是在树上可以完成一些区间操作问题 简单来说,就是把一棵树分成一条条的链,通过维护链上的信息来维护整棵树的信息 基础知识可以参考我的另外一篇博客:算法学习笔记(5): 最近公共祖先(LCA) 这里假设你已经掌握了上述博客中的所有相关知识,并清晰了其背后的原理 性质?发

算法学习笔记(11): 原根

原根 此文相对困难,请读者酌情食用 在定义原根之前,我们先定义其他的一点东西 阶 通俗一点来说,对于 $a$ 在模 $p$ 意义下的阶就是 $a^x \equiv 1 \pmod p$ 的最小正整数解 $x$ 或者说,$a$ 在模 $p$ 意义下生成子群的阶(群的大小) 再或者说,是 $a$ 在模

算法学习笔记(30):Kruskal 重构树

Kruskal 重构树 这是一种用于处理与最大/最小边权相关的一个数据结构。 其与 kruskal 做最小生成树的过程是类似的,我们考虑其过程: 按边权排序,利用并查集维护连通性,进行合并。 如果我们在合并时,新建一个节点,其权值为当前处理的边的权值,并将合并的两个节点都连向新建的节点,那么就可以得

算法学习笔记(3.1): ST算法

ST表 在RMQ(区间最值)问题中,著名的ST算法就是倍增的产物。ST算法可以在 \(O(n \log n)\) 的时间复杂度能预处理后,以 \(O(1)\) 的复杂度在线回答区间 [l, r] 内的最值。 当然,ST表不支持动态修改,如果需要动态修改,线段树是一种良好的解决方案,是 \(O(n)\

C++算法之旅、09 力扣篇 | 常见面试笔试题(上)算法小白专用

算法学习笔记,记录容易忘记的知识点和难题。详解时空复杂度、50道常见面试笔试题,包括数组、单链表、栈、队列、字符串、哈希表、二叉树、递归、迭代、分治类型题目,均带思路与C++题解

C++算法之旅、08 基础篇 | 质数、约数

算法学习笔记,记录容易忘记的知识点和难题。试除法、分解质因数、筛质数、约数个数、约数之和、最大公约数

算法学习笔记(1): 欧几里得算法及其扩展

扩展欧几里得算法详解 在了解扩欧之前我们应该先了解欧几里得算法 欧几里得算法 这是一个递归求最大公约数(greatest common divisor)的方法 $$ gcd(a, b) = gcd(b, a % b) $$ 可以通过一个类似的简单公式推导而来 好像叫做辗转相减法来着? $$ gcd(

算法学习笔记(3): 倍增与ST算法

倍增 目录倍增查找 洛谷P2249重点变式练习快速幂ST表扩展 - 运算扩展 - 区间变式答案倍增更多的用法优化矩形查询优化建图优化 DP作者有话说 倍增,字面意思即”成倍增长“ 他与二分十分类似,都是基于”2“的划分思想 那么具体是怎么样,我们以一个例子来看 查找 洛谷P2249 依据题面,我们知