线性基学习笔记
线性基学习笔记
——by sunzz3183
引入
学高斯消元后就要学线性基啦!建议先看懂高斯消元!
介绍
给定 个数 ,求一个基底。
基底就是一个线性空间,即线性基。
线性基中的 个数 , 中的每个数都可以被 的若干数通过异或得出。
求法
高斯消元
直接贴代码:
void add(int num){
for(int i=61;i>=0;i--)
if((num>>i)&1)
if(!p[i]){p[i]=num;return;}
else num^=p[i];
flg=1;//判断有没有0的存在
return;
}
清新易懂,我们从大到小来枚举当前 的第 位,如果发现 已经有元素了,就让 否则插入当前的 。
问题
线性基通常有如下三个用法:
-
查询一个数是否能被集合中其他数异或表示
-
求一个集合异或最大/最小值
-
求一个集合异或的第k大值
下列给定三种方法的代码
查询
bool ask(){
for(int i=61;i>=0;i--)
if(x>>i&1)x^=p[i];
return !x;
}
最大最小
inline int getmax(){
int ans=0;
for(int i=61;i>=0;i--)
ans=max(ans,ans^p[i]);
return ans;
}
inline int getmin(){
if(flg)return 0;//注意判零的存在
for(int i=0;i<=61;i++)
if(p[i])return p[i];
}
第 k 大
对 进行二进制拆分,然后进行选数。
注意,我们可能会在插入的时候插入了一个类似这样的一个数 。那么显然在求第 大的时候,会错序。
所谓我们要对 进行重构,让 成为 这样的数。
void rebuild(){
for(int i=61;i>=0;i--)
for(int j=i-1;j>=0;j--)
if(p[i]>>j&1)p[i]^=p[j];
for(int i=0;i<=61;i++)if(p[i])d[cnt++]=p[i];cnt--;
}
inline int getk(int k){
k-=flg;
if(k>=1ll<<cnt)return -1;
int ans=0,i=0;
while(k)ans^=(k&1)?d[i]:0,k>>=1,i++;
return ans;
}
本文作者:sunzz3183
本文链接:https://www.cnblogs.com/sunzz3183/p/17406945.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!