[学习笔记]省选(算法?数据结构?)·线性基

本文介绍了线性基的概念,包括其构造方法和查询操作,如最大异或和及判断一个数是否能被异或出。线性基是一种用于解决集合异或和问题的数据结构,文章通过实例和代码解释了其工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、开头

神犇MX:怎么样?xyz32768,你学不会后缀自动机,真是菜啊!
xyz32768:是啊,我本来就很菜啊!
神犇MX:你不服的话,再考你一道题:给定一个nn个数的数集,求一个子集,使这个子集的xor和最大?只需要输出这个xorxor和。n105n≤105并且每个数不大于260260
xyz32768:爆搜子集,O(2n)O(2n),我好像只会这样了。
神犇MX:看来你还是太菜,连线性基都不会,怎么可能会后缀自动机呢?
xyz32768:啊啊啊啊啊啊啊啊啊啊啊啊啊啊……(省略1099999910999999个“啊”)

二、介绍

一个nn个数的正整数集合S,这个集合的线性基是一个mm个正整数的集合:

A={a1,a2,a3,...,am}

线性基有两点性质:
:如果存在SSS′⊂SSS′内元素的xorxor和为tt,那么就一定存在AAAA′内的元素的xorxor和为tt,反过来也一样。简单的说,通过A集合内的元素xorxor出的值域与通过SS集合内的元素xor出的值域相同。
:线性基还有一个重要的性质:对于任何一个ii,要么ai不存在,要么aiai最高位的11在第i位上。

三、构造(插入一个新数)

集合SS为空时,线性基即集合A的每一个元素(即a1,a2,...a1,a2,...)都不存在。
向线性基中插入新数pp的方法:
从高到低扫描p的每一个二进制位,扫描到pp的第i位为11时,分两种情况:
如果ai不存在,那么令ai=pai=p并且结束扫描。
否则令p=p xor aip=p xor ai并继续扫描。
简单解释:假设插入新数pp之前的线性基为A,设AA′满足线性基的两个性质,那么在aiai不存在并且pp最高位的1在第ii位的情况下,令ai=p,得到的线性基仍然满足性质。
而在aiai存在的情况下令p=p xor aip=p xor ai是为了使pp的第i位为00,以此维护性质。这时候p异或上aiai之后等于待插入的新数,而两个相等的数的异或值总是00,这时候仍然满足线性基的性质
代码(代码中的orz表示线性基,orzi=1orzi=−1就表示orziorzi不存在):

void ins(ll p) {
    int i; for (i = m; i; i--) {
        if (!((p >> i - 1) & 1)) continue;
        if (orz[i] == -1) return (void) (orz[i] = p);
        else p ^= orz[i];
    }
}

合并两个线性基,就是把一个线性基中的元素暴力插入到另一个线性基里面。
代码:

cyx mer(cyx a, cyx b) {
    int i; for (i = m; i; i--)
        a.ins(b.orz[i]);
    return a;
}

四、查询

1、最大异或和

贪心。从高往低扫aa,对于一个ai,如果aiai存在,并且异或上aiai后会使结果更大,就异或上aiai。通过性质可以得出正确性。
代码:

ll max_xor() {
    int i; ll ans = 0; for (i = m; i; i--)
        if ((ans ^ orz[i]) > ans) ans ^= orz[i];
    return ans;
}

2、一个数pp能否被异或出

贪心,同样是利用性质。首先记下res=0。从高往低扫aa
对于一个ai,如果aiai存在,并且resres的第ii位与p的第ii位不等,则使res=res xor ai
如果最后res=pres=p,那么pp能被异或出。当然需要特判0
如果SS中有0,或者在构建线性基的过程中,存在一个待插入的数kk使得插入之前k能被异或出,那么存在一个非空子集的异或和为00
代码(不加特判0):

bool _xor(ll p) {
    int i; ll res = 0;
    for (i = m; i; i--) {
        if (orz[i] == -1) continue;
        if (((p >> i - 1) & 1) != ((res >> i - 1) & 1))
            res ^= orz[i];
    }
    return res == p;
}

五、题目

(待补充)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值