线性基--学习笔记

时隔半年蒟蒻还是没能完全理解线性基的原理,线性代数学的太差QAQ
但为了备考省选,还是稍微总结一下线性基的用法吧


线性基

给定一个原集合S,S的线性基能使用异或运算来表示原数集S使用异或运算能表示的所有数
如此大大缩小对原数集异或运算的查询

线性基的性质
  • 线性基内的数相互异或得到的集合与原数集得到的异或集合相同
  • 线性基内元素 a i a_i ai(第i位的元素,且不为0)其二进制表示下第 i i i位为1
  • 线性基的异或集合内不存在0
  • 若原数集大小为n,线性基大小为k,则共有 2 k 2^k 2k种不同的异或和,每个异或和出现次数为 2 n − k 2^{n-k} 2nk

线性基插入

高位向低位遍历线性基
如果 x x x二进制第 i i i位为1,检查线性基第 i i i
若线性基第 i i i位为0,在该位插入 x x x并退出,否则令 x x x异或线性基第 i i i位数值

void ins(lt x)
{
    for(lt i=62;i>=0;--i)
    if(x&((lt)(1)<<i))
    {
        if(!d[i]){d[i]=x;break;}
        else x^=d[i];
    }
} 

存在性查询

查询原数集的异或集合是否存在 x x x

按照插入的方式遍历一次线性基
若过程中发现 x = 0 x=0 x=0,则表示当前线性基已经可以通过异或得到原先的 x x x

bool query(lt x)
{
    for(lt i=62;i>=0;--i)
    if(x&((lt)(1)<<i)){
    	x^=a[i];
    	if(x==0) return true;
	}
	return false;
} 

查询异或最值

最大值

采用贪心思路
初始令 r e s = 0 res=0 res=0,由高位向低位遍历线性基
若res异或该位能使res增大,则令res异或该位数值

lt qmax(node tt)
{
    lt res=0;
    for(int i=62;i>=0;--i)
    if((res^tt.d[i])>res) res^=tt.d[i];
    return res;
}
最小值

线性基中的最小值,即为原集合相互异或能得到的最小值


第K小异或值

HDU - 3949 XOR
蒟蒻看的最懵逼的一部分,求第k小还要重构出新的基,以及令人懵逼的flag变量QAQ

void ins(lt x)
{
    for(lt i=62;i>=0;--i)
	if(x&(1ll<<i)){
    	if(!a[i]){ a[i]=x; return;}
    	else x^=a[i];
	}
    flag=1;
}

void rebuild()
{ 
    for(lt i=62;i>=0;--i)
	{
        if(!a[i])continue;
        for(lt j=i-1;j>=0;--j)
		{
            if(!a[j])continue;
            if(a[i]&(1ll<<j)) a[i]^=a[j];
        }
    }
    for(int i=0;i<=62;++i)
	if(a[i]) b[tot++]=a[i];
}

lt kth(lt k)
{
	rebuild();
	if(flag) k--;
	if(k==0) return 0;
	if(k>=(1ll<<tot)) return -1;
	
	lt res=0;
	for(int i=0;i<tot;++i)
	if(k&(1ll<<i)) res^=b[i];
	return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值