[笔记] 线性基
用处#
- 快速查询一个数是否可以被一堆数异或出来
- 快速查询一堆数可以异或出来的最大 / 最小值
- 快速查询一堆数可以异或出来的第 大值
性质#
- 原数列里的任何一个数都可以通过线性基里的数异或表示出来
- 线性基里任意一个子集的异或和都不为
- 一个数列可能有多个线性基,但是线性基里数的数量一定唯一,而且是满足性质一的基础上最少的。
实现#
构造
void insert(LL x){
rfor(i, lim, 0) if(x & (1LL << i)){
if(a[i]) x ^= a[i];
else{ a[i] = x; break; }
}
}
查询一个元素是否可以被异或出来
bool check(LL x) {
rfor(i, lim, 0) if(x & (1LL << i)) x ^= a[i];
return x == 0;
}
查询异或最大值
按位贪心.
LL askmax() {
LL ans = 0;
rfor(i, lim, 0) if(ans < (ans ^ a[i])) ans ^= a[i];
return ans;
}
查询异或最小值
一般来说就是线性基里的最小元素,特判 .
LL askmin() {
if(zero) return 0;
lfor(i, 0, lim) if(a[i]) return a[i];
}
查询异或第 小
重建线性基,使得不同位尽量不相互影响。
void rebuild() {
rfor(i, lim, 0) rfor(j, i - 1, 0) if(a[i] & (1LL << j)) a[i] ^= a[j];
lfor(i, 0, lim) if(a[i]) p[++cnt] = a[i];
}
类似树状数组二分第 小,同样特判 .
LL kth(int k) {
LL ans=0;
rfor(i, lim, 0) if(k & (1LL << i)) ans ^= p[i];
return ans;
}
查询排名
与查询第 小类似.
int rank(LL x) {
LL ans = 0;
rfor(i, cnt - 1, 0) if(x >= p[i]) ans += (1LL << i), x ^= p[i];
return ans + zero;
}
题目#
从 的最大XOR和路径可以看作任意一条从 的路径异或上若干个环。
分析出答案的补集就是线性基。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现