浅谈线性基
前言#
线性基是一种处理异或问题的利器,拥有优秀的时间复杂度
基本性质#
概念#
定义:给定数集 ,以异或运算张成的数集与 相同的极大线性无关集,称为原数集的一个线性基。
通俗地说,线性基是一个数的集合。每个序列都拥有至少一个线性基。取线性基中若干个数异或起来可以得到原序列中的任何一个数。
基本性质#
1、线性基中的数最高位互不相同
2、线性基中的数互相异或可以得到原序列中的任何一个数
3、线性基中的数没法异或出0
4、线性基是满足性质2的情况下的最小集合,且大小唯一。
5、线性基子集的异或和具有唯一性
证明咕咕咕
基本操作#
插入#
设数组 表示序列 的线性基,待插入数为 ,下标从 开始。
我们聚焦性质1,可以发现,如果想让线性基中的数最高位互不相同,就要用贪心的思想,在能匹配进去的时候匹配进去。所以我们将 转为二进制,从它的高位开始,如果当前位为 ,并且线性基 的第 位上没有数,那就赋成当前值 。
如果发现这时候第 位上有数,那么就让 异或上 后继续按最高位匹配。
为什么这样做是可行的?
不妨假设 在匹配时经过了 中的 个位置,分别为 至 那么我们将这些位置上的 异或起来,就能得到原来的 ,因为我们在匹配过程中,相当于每次失配的时候都把当前的 拆分成了 和 ,之后我们再用后半部分去匹配,因此我们把所有经过的位置的线性基中的数给异或起来,我们就得到了原数。
bool insert(ll x){
for(int i=60;i>=0;i--){
if(x>>i&1){
if(!p[i]){ p[i]=x;return true;}
x^=p[i];
}
}
return false;//判断能否插入成功
}
查最大值#
因为线性基中每个数的最高位互不相同,而且异或运算里每一位都是独立的,所以我们要想求异或后的全局最大值,我们只需要从高位向低位依次尝试加入后能否是当前答案变大即可。
ll found_max(){
ll ans=0;
for(int i=60;i>=0;i--) ans=max(ans,ans^p[i]);
return ans;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】