线性基模板

时间:2019-08-14
本文章向大家介绍线性基模板,主要包括线性基模板使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

线性基构造方法
对于每一个数,我们找出他的最高位的 1 在第 i 位, 如果此时 Pi 为零,就将这个数加入线性基,否则异或 Pi 继续找。然后我们就可以在 0 到 k 位上处理好每一位的线性基。这样得到的线性基保证每一位都能有对应的最大值。

void get_p(LL x)
{
    for(int i=62;i>=0;i--)
    {
        if((x>>(LL)i))
        {
            if(!p[i])
            {
                p[i]=x;
                break;
            }
            x^=p[i];
        }
    }
}

求最大异或和
在我们得到的线性基中,从高位到低位用贪心贪掉每一个元素,如果异或了这个元素变大就异或他。

    LL ans=0;
    for(int i=62;i>=0;i--)
        if((ans^p[i])>ans)ans^=p[i];

查询某个数
我们也是从低到高扫这个数的每一位,如果这第 i 位为 1,就异或上 Pi,然后知道处理到最后一位。如果变成 0 了,那么就是可以的。

bool check(int x)//查询能否异或成某个数
{
    for(int i=31;i>=0;i--)
    {
        if(x>>i)x^=p[i];
    }
    return x==0;
}

线性基求交
有一道模板题,不过要用到线段树来优化查询
题目链接:https://ac.nowcoder.com/acm/contest/884/B

#include<bits/stdc++.h>
using namespace std;
const int maxx=5e4+10;
int a[maxx<<2][32];
void insert(int x,int temp)//构造线性基
{
    for(int i=31;i>=0;i--)
    {
        if(x>>i)
        {
            if(!a[temp][i])
            {
                a[temp][i]=x;
                break;
            }
            x^=a[temp][i];
        }
    }
}
bool check(int x,int temp)//查询能否异或成某个数
{
    for(int i=31;i>=0;i--)
    {
        if(x>>i)x^=a[temp][i];
    }
    return x==0;
}
void pushup(int temp)//线性基求交
{
    int t1[32],t2[32],l=temp*2,r=temp*2+1;
    for(int i=0;i<32;i++)
        t1[i]=t2[i]=a[l][i];
    for(int i=0;i<32;i++)
    {
        if(a[r][i])
        {
            int x=a[r][i],t=0;
            for(int j=31;j>=0;j--)
            {
                if(x>>j)
                {
                    if(!t1[j])
                    {
                        t1[j]=x,t2[j]=t;
                        break;
                    }
                    x^=t1[j],t^=t2[j];
                }
            }
            if(!x)insert(t,temp);
        }
    }
}
void build(int l,int r,int temp)
{
    if(l==r)
    {
        int s,t;
        scanf("%d",&s);
        while(s--)
        {
            scanf("%d",&t);
            insert(t,temp);
        }
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,temp*2);
    build(mid+1,r,temp*2+1);
    pushup(temp);
}
bool query(int l,int r,int p,int q,int x,int temp)
{
    if(p<=l&&r<=q)
    {
        return check(x,temp);
    }
    int mid=(l+r)/2;
    bool res=1;
    if(p<=mid)res&=query(l,mid,p,q,x,temp*2);
    if(q>mid)res&=query(mid+1,r,p,q,x,temp*2+1);
    return res;
}
int main()
{
    int n,m;
    cin>>n>>m;
    build(1,n,1);
    int p,q,x;
    while(m--)
    {
        scanf("%d%d%d",&p,&q,&x);
        if(query(1,n,p,q,x,1))printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

$flag 上一页 下一页