题意

给定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. English trip -- VC(情景课) 7 B Clothing 服装

    xu言: 不要使用中式的思维去思考西方的语义!!!切记切记 words a tie   领带 a blouse  女士衬衣 a sweater  毛衣 a skirt  短裙 a jacket   夹 ...

  2. spting Boot 创建一个springBoot项目

    spting Boot 创建一个springBoot项目 1)学习springBoot使用软件:IDEA软件(前面的文章有安装idea的过程). 也可以使用另一种方法在https://start.sp ...

  3. Tomcat类加载器破坏双亲委派

    转载:https://blog.csdn.net/qq_38182963/article/details/78660779 http://www.cnblogs.com/aspirant/p/8991 ...

  4. Python将列表作为栈和队列

    Collections中的各种方法 阅读目录(Content) 一.各种方法介绍 二.代码部分 回到顶部(go to top) 一.各种方法介绍 Counter 统计个数   elements  mo ...

  5. python中的注释,输入输出和编码及文件

    1.单行注释 以井号( # )开头,右边的所有内容当做说明2.多行注释 以三对单引号(’’’注释内容’’’)将注释包含起来以‘# ’是注释的标识符,可以记录当前代码所代表的意义,解释器会自动忽略这部分 ...

  6. 微信小程序跨页面获取数据示例

    index.wxml <navigator class="navs" url="{{urls}}"> 中国 </navigator> i ...

  7. c++多态多实例

    #include <bits/stdc++.h> using namespace std; class A { public: A() { cout << "构造A& ...

  8. [工作]双核系统struts-config.xml

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC & ...

  9. 对HTML(HyperText Markup Language)的认识以及总结

    一.HTML的基础结构 以上图片可以看出HTML的基础结构: 文档声明+<html>根元素(也叫顶级元素)------><html>里包括<head>元素+& ...

  10. Alpha阶段敏捷冲刺---Day7

    一.Daily Scrum Meeting照片 二.今天冲刺情况反馈     今天是Alpha阶段敏捷冲刺的最后一天,今天我们将对这一阶段的任务进行扫尾工作,我们打算完成之前设想的程序的所有功能,包括 ...