线性基学习笔记
概念
定义:给定数集
简单地说,线性基是一个数的集合。每个序列都拥有至少一个线性基。取线性基中若干个数异或起来可以得到原序列中的任何一个数。
性质
- 性质一
- 取线性基中若干个数异或起来可以得到原序列中的任何一个数。
- 性质二
- 线性基中任意选择若干个数异或不为零。
- 性质三
- 线性基内部的数个数唯一,且在保持性质一的前提下,数的个数是最少的。
证明
性质二
若
性质一
分类讨论插入的数
若不能插入线性基,显然就是在线性基中有几个数和它异或之后变成了零,那么也就是说线性基中若干个数异或后可以为
若可以插入,设插入到了第
则
所以
性质三
如果原集合中每个数都被插入进了线性基,则显然成立,如果插入顺序是
那么无论怎么改变顺序也一定有一个数插不进去。所以个数是一定的。
若去掉线性基里面的任何一个数,都会使得原序列里的数无法用线性基里的数异或得到,所以没有多余的元素。
所以线性基的元素个数在保持性质一的前提下,一定是最少的。
基操
插入
将
则样子能保证
void insert(int k) {
for(int i=60;i>=0;i--) {
if(!(k&(1LL<<i))) continue;
if(!p[i]){
p[i]=k;
break;
}
k^=p[i];
}
}
最大值
接着采取贪心的思想,从线性基的最高位开始,若当前的答案异或线性基的这个元素可以变得更大,那么就异或它。因为线性基的
int maxXor(){
int res=0;
for(int i=60;i>=0;i--) res=max(res,(res^p[i]));
return res;
}
最小值
同样是贪心,最大值要看情况。
for(int i=60;i>=0;i--) ans=min(ans^p[i],ans);
小值
直接看代码吧,我知道怎么讲:(。
void rebuild(){
for(int i=60;i>=0;i--)
for(int j=i-1;j>=0;j--)
if(p[i]&(1ll<<j))
p[i]^=p[j];
for(int i=0;i<=60;i++)
if(p[i])
d[tot++]=p[i];
}
int Getnumk(int k){
if(k>=(1ll<<tot)) return -1;
int ans=0;
for(int i=62;i>=0;i--)
if((k>>i)&1)
ans^=d[i];
return ans;
}
6666
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】