ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

「笔记」线性基

2021-06-30 12:03:52  阅读:225  来源: 互联网

标签:基中 int res 元素 笔记 异或 线性


概念

线性基是向量空间的一组基,通常可以解决有关异或的一些题目。-Oi-wiki

线性基就是一个有着特殊性质的集合,在处理某些情况下的异或问题有着意想不到的效果。

假设我们用 \(p\) 数组来存线性基。

线性基可以由给出的一组元素相互异或而来。

而 \(p_i\) 中的元素表示该元素二进制下 \(1\) 的最高位是第 \(i\) 位。

性质

  • 线性基具有普通集合所具有的性质,即确定性、互异性、无序性。
  • 线性基中每个元素的最高位不同。(根据 \(p\) 数组定义比较显然。)
  • 线性基中没有异或和为 \(0\) 的子集。(每个元素的最高位不同,异或起来最高位一定不会为 \(0\)。)
  • 线性基中任意多元素的异或和的值域等于原集合中任意多元素的异或和的值域。
  • 线性基在满足上一个条件的情况下,所包含元素个数是最少的。
  • 线性基中不同的元素异或出来的值是不同的。

构造

一下情况都是在二进制下进行。

假设插入一个元素 \(x\) 。

  • 从高位向低位判断,直到遇到该元素某位上为 \(1\),设该位为 \(i\)。
  • 然后判断 \(p_i\) 是否有值,如果没有把 \(x\) 存到 \(p_i\) 中,否则将 \(x\) 与 \(p_i\) 异或然后重复上面的操作。(将 \(x\) 与 \(p_i\) 异或后 \(x\) 的最高位上的 \(1\) 就没了,至于变成了啥也无所谓了)

把所有元素都插入后,我们就得到了这组元素的线性基。

这样构造的线性基满足它该有的所有性质,\(p_i\) 数组也符合定义。

Code:

void Insert(int k) {
    for(int i = Max; i >= 0; --i) { // Max 表示二进制最高位
        if(!(k & (1ll << i))) continue;
        if(!p[i]) { p[i] = k; return ; }
        k ^= p[i];
    }
}

操作

求最大值

给你一堆元素,挑几个异或起来,是他们的值最大,输出最大值。

我们先用这组元素构造出线性基。然后贪心的进行选择,选高位的肯定比低位的要更优。

所以我们从高位向低位遍历,如果异或上 \(p_i\) 更优就异或。最后的结果就是要求的最大值。

为什么能直接用?线性基的元素都是通过已知的元素异或而来,肯定是正确的。

Code:

int Query() {
    int res = 0; 
    for(int i = Max; i >= 0; --i) res = max(res, res^p[i]);
    return res;

求一个数是否能被表示出来

把这个数扔到线性基里跑一边就行。

每次挑这个数的最高位进行异或,都能把最高位消掉。

如果最后这个数为 \(0\) ,说明该数可以被表示出。

线性基合并

把一个线性基的每个元素插入另外一个线性基即可。

查找严格次大值

先找到最大值,然后从低位向高位枚举,然后找到两者都为一的异或上, 然后退出即可。

例题

下午再补先咕咕

鸣谢

题解 P3812 【模板】线性基 - rui_er

线性基知识整理 - Aliemo

线性基 - KnightL

标签:基中,int,res,元素,笔记,异或,线性
来源: https://www.cnblogs.com/Silymtics/p/14953835.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有