线性基学习笔记

1.可以用于处理与异或有关的问题(异或最大值,一堆数中有无子集异或等于0,某数在一堆数异或中的排名)

2.插入操作

x=read();
for(int j=60;j>=0;j--)
{
    //cout<<(int)((int)1<<j)<<"\n";
    if((int)((int)1<<j)&x)
    {
        if(p[j]==0)
        {
            p[j]=x;
            break;
        }
        else
            x^=p[j];
    }
}

3.性质

(1)、线性基内任何子集的异或和不为0。

(2)、线性基外的所有数必能由线性基内一些数异或得到。

证明:

(1)、如果插入数x后异或和为0,则x^p1^p2^……^pt=0。则x在插入时,异或p1,p2……后即为0,就不会插入x。

(2)线性基外的数没有被插入,则肯定在中途被异或成0了,则他可以被线性基中一些数异或得到。

4.查询异或最大值:

直接在线性基中贪心,如果异或p[i]变得更大,就异或p[i]。

首先由性质(2),原序列所有数都能被线性基内的数异或得到。那么最大值一定可以通过线性基中数异或得到。

pi即表示可以异或一个二进制最高位为i的数。

如果现在ans这一位为0,那肯定异或p[i]后变得更大,如果这一位是1,那异或p[i]这一位变成0了,随便咋个异或后头的数都莫得办法变大了,那就不异或。

代码如下:

int ans=0;
for(int i=52;i>=0;i--)
{
    ans=max(ans,ans^p[i]);
}
View Code

5.

查询排名第k小的数。

首先如果有异或等于0的,先把k--,因为线性基里头莫得0。然后先把p数组 \( n^{2} \)预处理一哈,如果p[i]&(1<<j) p[i]^=p[j] (j=i;j>=0;j--),就保证了靠这一位影响不到后头。然后就将k转成二进制,从0枚举到最高位,如果k第i为为1,就把答案异或上p中的从0到最高位上第i个元素即可。

6.

例题

洛谷P4301

P3265 (实数线性基)

P3292

posted @ 2020-03-02 21:27  精海臭脚  阅读(157)  评论(0编辑  收藏  举报