线性基

线性基用于解决异或相关的问题。


如何构造线性基?

设 $ p $ 为线性基的集合。

插入一个数 $ x $ 时,枚举其最高位 $ i $ ,若 $ p_i $ 不存在,令 $ p_i = x $ 并退出,否则令 $ x = x : xor : p_x $ 。

void ins(ll x)
{
	for(ll i=SIZE-1;i>=0;i--)
	{
		if(!(x>>i))continue;
		if(!p[i]){p[i]=x;break;}
		x^=p[i];
	}
}

性质 $ 1 $ : 原数列里的任何一个数都可以通过线性基里的数异或表示出来。

性质 $ 2 $ : 线性基没有异或和为 $ 0 $ 的子集。

性质 $ 3 $ : 一个数列的线性基里(可能多个),数的数量一定唯一,且满足性质 $ 1 $ 。


性质 $ 1 $ 显然。

性质 $ 2 $ : 假设存在 $ p_1 \bigoplus p_2 \bigoplus p_3 =0 $ ,则 $ p_1 \bigoplus p_2 = p_3 $ ,故 $ p_3 $ 不会被插入,矛盾。

性质 $ 3 $ : 分类讨论。

$ 1. $ 当所有数都能被插入线性基时,显然成立。

$ 2. $ 若元素 $ x $ 无法插入线性基,则 :

$ ( : 1 : ) $ $ x=0 $ 。肯定无法插入线性基。

$ ( : 2 : ) $ 存在 $ p_a \bigoplus p_b \bigoplus ... \bigoplus p_c =x $ 。就是说插入 $ p_c $ 之后, $ x $ 就必定无法插入了。故 $ x $ 与 $ p_c $ 相排斥,但两者只影响线性基中一位的取值。

综上,性质 $ 3 $ 得证。


查询一个数能否被异或得到

从高位向低位找,若该位为 $ 1 $ 则异或该位的线性基。

由性质 $ 1 $ ,若最后的值为 $ 0 $ ,说明该数能够被表示出来。

bool find(ll x)
{
	for(ll i=SIZE-1;i>=0;i--)
	if(x>>i)x^=p[i];
	return !x;
}

查询异或最大值

按位贪心。若当前答案异或上 $ p_i $ 的值变大,则异或 $ p_i $ 。

ll qmax()
{
	ll ans=0;
	for(ll i=SIZE-1;i>=0;i--)
	ans=max(ans,ans^p[i]);
	return ans;
}

查询异或最小值

答案即线性基中的最小元素。

ll qmin()
{
	if(flag)return 0;//flag表示是否存在0这个数
	for(ll i=0;i<SIZE;i++)
	if(p[i])return p[i];
}

求排名和大小以后会补。

前缀线性基板子 CF1100F

posted @ 2023-08-06 19:34  SError  阅读(9)  评论(0编辑  收藏  举报