线性基笔记

线性基

在线性代数中,对于向量组 a 1 , a 2 , . . . , a m a_1,a_2,...,a_m a1,a2,...,am我们把其张成空间的一组线性无关的基称为该向量的线性基,

用途

  • 快速查询一个数是否可以被一堆数异或出来
  • 快速查询一堆数可以异或出来的最大/最小值
  • 快速查询一堆数可以异或出来的第k大值

性质

  • 原数列里的任何一个数都可以通过线性基里的数异或表示出来
  • 线性基里任意一个子集的异或和都不为0
  • 一个数列可能有多个线性基,但是线性基里数的数量一定唯一,而且是满足性质一的基础上最少的

证明性质二:
如果集合内存在 a 1 ⊕ a 2 ⊕ . . . ⊕ a m = 0 a_1 \oplus a_2 \oplus...\oplus a_m=0 a1a2...am=0,那么一定存在一个 a k a_k ak使得 a 1 ⊕ a 2 ⊕ . . . ⊕ a m ( 不 包 含 a k ) = a k a_1 \oplus a_2 \oplus...\oplus a_m(不包含a_k)=a_k a1a2...am(ak)=ak

原理 & 实现

将一个数插入线性基:

void insert(LL x)
{
	for(int i = 62; ~i; -- i)
	{
		if(x & (1ll << i))
		{
			if(!p[i])
			{
				p[i] = x;
				cnt ++;
				break;
			}
			else x ^= p[i];
		}
	}
}
  • 从高位到低位进行
  • 如果 x ( 2 ) x_{(2)} x(2) i i i位为1,判断 p [ i ] p[i] p[i]是否插入,没有就插入并且退出,否则就异或上 p [ i ] p[i] p[i]去进行下一位操作 。

查询异或最大值

直接贪心异或即可

LL qmax()
{
	LL ans = 0;
	for(int i = 62; ~i; -- i)
		ans = max(ans, ans ^ p[i]);
	return ans;
}

查询异或最小值

一般来说线性基里的最小元素就是异或最小值,只有原数列里存在0是,最小值才是0(线性基里不能表示出0),我们直接在插入时记录一下即可

查询第k大异或和

只需按照 k k k的二进制分解去选即可,比如第 3 = ( 11 ) 2 3=(11)_2 3=(11)2小的元素就是排序之后的线性基的第一个和第二个的异或,排序后,线性基从小到大排列,因为 p p p数组的性质决定了没有两个最高位相同的数,所以这样可以求出区间第k大异或和

合并两个线性基

只需要将一个线性基中的元素插入到另一个线性基即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值