线性基学习笔记
这个东西的作用在于:
-
快速求一个数能否被一些数异或得到
-
求一些数中任选几个数的异或最大值、最小值
-
求一些数中的异或第 k 大值
它有如下性质:
-
原数列中的所有数都可以通过线性基里的数异或出来
-
任意子集异或和不为0
-
一个数列可能有多个线性基,但是线性基里数的数量一定唯一,而且是满足性质一的基础上最少的
操作
插入
假设当前插入的值为 \(x\),\(x\) 的最高位为 \(i\):
-
如果当前位是空的,直接插入 \(x\)
-
如果当前位已经有数 \(a_i\),那么令 \(x=a_i \oplus x\),重复此过程,直到 \(x=0\)
如果 \(x=0\),就证明可以表示,否则就要加新数
用这个方法,可以确定一个数能否被表示
求最值
先看最小值,因为线性基位数是不断变多的,所以最小值异或上什么都必然增加,所以最小值就是线性基中的最小值
接下来是最大值,可以顺序跑,如果当前位是 0,就异或 \(a_i\),这样一定会更大
例题
线性基模板
https://www.gxyzoj.com/d/gxyznoi/p/54
就是求最值,注意 long long
点击查看代码
#include<cstdio>
#define ll long long
using namespace std;
int n;
ll a[60];
void insert(ll x)
{
for(int i=51;i>=0;i--)
{
if(x&(1ll<<i))
{
if(!a[i])
{
a[i]=x;
break;
}
else x^=a[i];
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
ll x;
scanf("%lld",&x);
insert(x);
}
ll ans=0;
for(int i=51;i>=0;i--)
{
if(ans&(1ll<<i)) continue;
ans^=a[i];
}
printf("%lld",ans);
return 0;
}
[BeiJing2011] 元素
https://www.gxyzoj.com/d/gxyznoi/p/P47
显然的,假设当前数为 x,如果 x 能加入之前已选元素的基中,x 就可以被选
所以可以将值从大到小排序,然后依次插入判断即可
albus就是要第一个出场
https://www.gxyzoj.com/d/gxyznoi/p/P48
一个性质,如果线性基中有 s 个数,总共有 n 个数,那么能组成 \(2^s\) 个数,每个数 \(2^{n-s}\) 个
所以因为是大小,所以根据有 1 的位置,计算在这 \(2^s\) 个数的排名即可
玛里苟斯
https://www.gxyzoj.com/d/gxyznoi/p/P49
根据答案的范围,可以发现,当 \(k\ge 3\) 时,至多有 \(2^{21}\) 种不同的数
所以当 \(k\ge 3\) 时,直接建出线性基暴搜即可
对于 k=1,如果所有数的第 i 位存在 1,那么就有 \(\frac{1}{2}\) 的概率异或后为 1
对于 k=2,假设当前数为 \(x=2^{a_1}+2^{a_2}+\dots\),那么 \(x^2=\sum_{i=1}^{len}\sum_{j=1}^{len} 2^{i+j}*f(i,j)\)
这里的 \(f(i,j)\) 就是两者同为 1 的概率
如果所有数字中的两位都相同,就是 \(\frac{1}{2}\),否则就是 \(\frac{1}{4}\)
DZY Loves Chinese II
好吧,是构造
先考虑最简单的情况,就是判断一个点和其他点的连通性
那么如果使用异或的思想,判断有没有断干净,就是使得跟这个点相连的所有边的异或和为 0
继续推广,可以发现,只要满足上面的条件满足时,就可以判断一个边集是否能断开
所以接下来是构造方法,可以任意 dfs 一个生成树,如果与 i 连通的边未被赋值,树边访问,非树边随机即可
shallot
https://www.gxyzoj.com/d/gxyznoi/p/P51
因为每一次删除都会导致后面加入的全部重做,所以要尽量避免删除操作
如果将每一次操作都标上时刻,那么每个数存在的就是一个时间段
那么可以枚举时间,然后加入存在的数,可以线段树分治优化
[BeiJing2011]梦想封印
https://www.gxyzoj.com/d/gxyznoi/p/P52
显然的,删边难做,倒过来加边
可以发现,最终的东西简化后就是先以 1 为根建立生成树,组成是一些环+一条链
因为环不受限制,为了统计情况数,可以建立线性基
接下来是如何对链去重,因为异或后最小值为 x 的两个数,其他得到的数必然相同
所以可以用 set,储存不同的最小值
[SCOI2016] 幸运数字
https://www.gxyzoj.com/d/gxyznoi/p/P53
题目可以转化为求这条路径上的线性基
显然,线性基是可以合并的,所以可以倍增,记录每一段的线性基,然后求解时跳 LCA 即可
Shortest Path Queries
https://www.gxyzoj.com/d/gxyznoi/p/P938G
看到删除,线段树分治,对于环,扔进线性基,接下来是如何求树边链长的问题
涉及到联通块,考虑可撤销并查集,连边的时候因为是父亲和父亲连边,所以要异或上到父亲的权值

浙公网安备 33010602011771号