题意

给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大。
\(1≤n≤50,0≤S_i≤2^{50}\)

分析

模板题。
推荐一篇好博客
现在我来证明一下线性基的性质。

性质

这说的线性基是真正的线性基,不是程序里面的。

  1. 设线性基的异或集合中不存在0。
    这个是个构造,不用证明。数集T本身就是线性基,而它的异或集合中当然存在0。
  2. 线性基的异或集合中每个元素的异或方案唯一,其实这个跟性质1是等价的。
    如果异或方案有多种,那么这些方案去掉公共部分后异或起来就是0,与性质1矛盾。
  3. 线性基中元素互相异或,异或集合不变。
    考虑把这两个异或了的两个元素a,b提出来,剩下的组合,把这两个元素的贡献加入组合中,无论是否异或贡献都是a^b,a,b,0这4中情况
  4. 线性基二进制最高位互不相同。
    这也是一个构造。如果原集有两个最高位相同,那么异或一下就不同了。由于性质3,异或集合不变,所以新的这个集合还是线性基。
  5. 如果线性基是满的,它的异或集合为\([1,2^n-1]\)。
    没什么好说的。

标准化

就是querykth那样的构造,一定可以把线性基造成每个元素只有最高位为1的为1的集合。

代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXB=51;
struct LB
{
    ll d[MAXB],p[MAXB];
    int cnt;

    LB()=default;

    bool insert(ll x)
    {
        for(int i=MAXB-1;i>=0;--i)
            if(x&(1LL<<i))
            {
                if(!d[i])
                {
                    d[i]=x;
                    break;
                }
                x^=d[i];
            }
        return x>0;
    }

    ll qmax()
    {
        ll res=0;
        for(int i=MAXB-1;i>=0;--i)
            if((res^d[i])>res)
                res^=d[i];
        return res;
    }

    ll qmin()
    {
        for(int i=0;i<MAXB;++i)
            if(d[i])
                return d[i];
        return 0;
    }

    void rebuild()
    {
        for(int i=MAXB-1;i>=0;--i)
            for(int j=i-1;j>=0;--j)
                if(d[i]&(1LL<<j))
                    d[i]^=d[j];
        cnt=0;
        for(int i=0;i<MAXB;++i)
            if(d[i])
                p[cnt++]=d[i];
    }

    ll qkth(ll k)
    {
        rebuild();
        if(k>=(1LL<<cnt))
            return -1;
        ll res=0;
        for(int i=cnt-1;i>=0;--i)
            if(k&(1LL<<i))
                res^=p[i];
        return res;
    }
}T;

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int n;
    read(n);
    while(n--)
    {
        static ll x;
        read(x);
        T.insert(x);
    }
    printf("%lld\n",T.qmax());
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

LG3812 【模板】线性基的更多相关文章

  1. [P3812][模板]线性基

    解题关键:求异或最大值.线性基模板题. 极大线性无关组的概念. 异或的值域相同. #include<cstdio> #include<cstring> #include< ...

  2. LG3812 「模板」线性基 线性基

    问题描述 LG3812 题解 线性基是一类擅长解决异或问题的数据结构(也不算数据结构吧...就是一种玄学的东西) 对于数列 \(a\) ,它的线性基 \(d\) 为 出现 \(1\) 的最高位在第 \ ...

  3. 线性基【p4570】 [BJWC2011]元素

    题目描述-->p4570 [BJWC2011]元素 题目大意 给定一些矿石的编号与价值,我们想要得到最大的价值和,并且选定物品的编号异或之和不为0. 分析 线性基就不多bb了,来这里->p ...

  4. P3812 【模板】线性基

    P3812 [模板]线性基 理解 :线性基 类似于 向量的极大无关组,就是保持原来所有数的异或值的最小集合, 求解过程也类似,可以 O( 60 * n )的复杂度求出线性基,线性基有许多性质,例如 线 ...

  5. 洛谷P3812 【模板】线性基 [线性基]

    题目传送门 线性基 题目描述 给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大. 输入输出格式 输入格式: 第一行一个数n,表示元素个数 接下来一行n个数 输出格式: 仅一行 ...

  6. 洛谷P3812 【模板】线性基

    题目背景 这是一道模板题. 题目描述 给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大. 输入输出格式 输入格式: 第一行一个数n,表示元素个数 接下来一行n个数 输出格式: ...

  7. 模板【洛谷P3812】 【模板】线性基

    P3812 [模板]线性基 给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大. code: #include <iostream> #include <cs ...

  8. 题解——洛谷P3812【模板】线性基

    学了下线性基 使用好像并不复杂 打了板子 但是要注意位运算优先级 #include <cstdio> #include <algorithm> #include <cst ...

  9. luogu 3812 【模板】 线性基

    线性基是一个支持在集合里插入数并查询最大子集异或值 #include<iostream> #include<cstdio> #include<cstring> #i ...

随机推荐

  1. AsyncTask用法和异步加载图片

    AsyncTask:是Android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI ...

  2. Confluence 6 选项 1 – 在 Confluence 中手动重建用户和用户组

    当你只有少量的用户和用户组的时候,使用这个方法. 使用 Confluence 的系统管理员登录 Confluence. 进入用户目录管理界面,然后移动 内部目录(internal directory) ...

  3. 『cs231n』绪论

    笔记链接 cs231n系列所有图片笔记均拷贝自网络,链接如上,特此声明,后篇不再重复. 计算机视觉历史 总结出视觉两个重要结论:1.基础的视觉神经识别的是简单的边缘&轮廓2.视觉是分层的 数据 ...

  4. hdu-5465-二维BIT+nim

    Clarke and puzzle Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  5. iOS UI-表格控制器(UITableView)-基本使用

    tableView的常见属性 cell的常见属性 一.一般情况 #import "ViewController.h" @interface ViewController ()< ...

  6. CachedThreadPool里的线程是如何被回收的?

    线程池创建线程的逻辑图: 我们分析CachedThreadPool线程池里的线程是如何被回收的. //Executors public static ExecutorService newCached ...

  7. html <a>标签介绍

    <a href="javascript:void(0)" click="function(){}" />= a 标签样式     一组专门的预定义的 ...

  8. Awk 从入门到放弃 (7) 动作总结之二

    第一题: 使用if语句进行判断

  9. ZOJ 3829 Known Notation 贪心 难度:0

    Known Notation Time Limit: 2 Seconds      Memory Limit: 65536 KB Do you know reverse Polish notation ...

  10. Nodejs之mssql模块的封装

    在nodejs中,mssql模块支持sqlserver数据库操作.今天将mssql模块的某些功能封装为一个类,方便以后调用.封装的功能有执行存储过程,执行查询语句操作等.如果本篇文章对大家有帮助,那就 ...