点此看题面

大致题意: 让你把\(n\)个数分成两部分,使得在两部分异或和之和最大的前提下,两个异或和中较小的那个尽量小。输出最优的较小异或和。

线性基

关于线性基,可以看一下这篇博客:线性基入门。

解题思路

首先,做这题要有一定的位运算常识。

我们求出所有数的异或和,记作\(s\)。

则对于\(s\)二进制下每一位,我们进行分类讨论:

  • 如果这一位是\(1\)。则划分出的两个集合的异或和这一位必然分别是\(0\)或\(1\),即:两个集合中这一位之和是固定不变的。
  • 如果这一位是\(0\)。则划分出的两个集合的异或和这一位必然是全\(0\)或全\(1\)。

既然我们要让总和最大,由于\(1\)位上的总和不变,则显然应该先去考虑\(0\)位,使\(0\)位尽量为两个\(1\)。

然后,借助线性基的思想,我们修改一下线性基的操作方式,就可以轻松求解此题啦。

对于插入

对于插入,由于我们刚刚已经总结出使\(0\)位尽量为两个\(1\),因此,我们在插入时要优先考虑\(0\)位。

具体实现时,就是先对\(0\)位从高到低扫一遍判断是否可以插入,然后对\(1\)位从高到低扫一遍判断是否可以插入。

先扫\(0\)我们就相当于把每个最后插入到\(1\)位的数的\(0\)位全变成了\(0\),使得操作\(1\)位不会影响到\(0\)位,为后面的询问奠定了基础。

对于询问

我们先从高到低扫一遍\(0\)位,如果当前\(ans\)这一位上是\(0\),则我们尽量使其为\(1\)。

由于这一位上的数要么二进制下这一位是\(1\)(可以把\(ans\)这一位上变成\(1\)),要么这个数就是\(0\)(异或\(0\)没有任何影响),因此直接将\(ans\)异或上当前这一位的数即可。

然后从高到低扫一遍\(1\)位,如果\(ans\)这一位是\(1\),由于我们要让这个数尽量小,就异或上当前这一位的数即可(理由同上)。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define RL Reg LL
#define Con const
#define CI Con int&
#define CL Con LL&
#define I inline
#define W while
#define N 100000
#define LL long long
using namespace std;
int n;LL s,a[N+5];
class FastIO
{
private:
#define FS 10000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
class LinearBasis//线性基
{
private:
#define P 60
LL v[P+5];
public:
#define ins() {if(!v[i]) return (void)(v[i]=x);x^=v[i];}
I void Insert(RL x)
{
RI i;for(i=P;~i;--i) if(!(s>>i&1)&&x>>i&1) ins();//优先考虑0位
for(i=P;~i;--i) if(s>>i&1&&x>>i&1) ins();
}
I LL Query()
{
RI i;RL ans=0;for(i=P;~i;--i) !(s>>i&1)&&!(ans>>i&1)&&(ans^=v[i]);//尽量使0位变成1
for(i=P;~i;--i) s>>i&1&&ans>>i&1&&(ans^=v[i]);return ans;//尽量使1位更小
}
}B;
int main()
{
RI i;for(F.read(n),i=1;i<=n;++i) F.read(a[i]),s^=a[i];//统计所有数异或和
for(i=1;i<=n;++i) B.Insert(a[i]);return printf("%lld",B.Query()),0;//求解并输出答案
}

【LOJ6060】「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基)的更多相关文章

  1. LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)

    LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...

  2. Loj #6069. 「2017 山东一轮集训 Day4」塔

    Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...

  3. Loj #6073.「2017 山东一轮集训 Day5」距离

    Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...

  4. Loj 6068. 「2017 山东一轮集训 Day4」棋盘

    Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...

  5. 「2017 山东一轮集训 Day5」苹果树

    「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...

  6. 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)

    [LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...

  7. loj6068. 「2017 山东一轮集训 Day4」棋盘 二分图,网络流

    loj6068. 「2017 山东一轮集训 Day4」棋盘 链接 https://loj.ac/problem/6068 思路 上来没头绪,后来套算法,套了个网络流 经典二分图 左边横,右边列 先重新 ...

  8. LOJ #6074. 「2017 山东一轮集训 Day6」子序列

    #6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...

  9. 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP

    [LOJ6077]「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k ,请求出长度为 n的逆序对数恰好为 k 的排列的个数.答案对 109+7 取模. 对于一个长度为 n 的排列 p ...

  10. loj #6077. 「2017 山东一轮集训 Day7」逆序对

    #6077. 「2017 山东一轮集训 Day7」逆序对   题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...

随机推荐

  1. Oracle RAC集群添加节点

    一,节点环境 所有节点分发/etc/hosts,这里我添加两个节点,一个是上次删除的节点,另一个是什么都没有的节点,尝试添加 服务器介绍什么的都在这hosts文件了,大家自己琢磨下 [grid@nod ...

  2. oracle 单实例DG(闪回技术四)

    一,flashback Oracle Flashback技术是一组数据库特性,它可以让你查看数据库对象的过去状态,或者将数据库对象返回到以前的状态,而无需使用基于时间点的介质恢复.根据数据库的变化,闪 ...

  3. lnmp 优化

    一,版本信息优化 重启 直接更改版本号: 在源码包里改 第二个要改的地方 第三个需要更改的 改完后编译安装,下次我直接写进编译脚本上

  4. Hsl PLC

    https://github.com/dathlin/HslCommunication 地址

  5. TOJ 1690 Cow Sorting (置换群)

    Description Farmer John's N (1 ≤ N ≤ 10,000) cows are lined up to be milked in the evening. Each cow ...

  6. 3d旋转卡牌

    做成向中心缩放就行了,和旋转效果一样的

  7. 把linux图形启动界面修改成命令行界面

    由于图形界面比较耗资源,需要把启动界面修改成命令行界面,怎么修改呢? 1.vim /etc/inittab 2.把id:5:initdefault:改成 id:3:initdefault: 3.重启即 ...

  8. vscode插件推荐

    在扩展(Ctrl+Shift+X)中直接搜索这些插件的名字安装即可 1.HTML Snippets 超级使用且初级的H5代码片段以及提示 2.HTML CSS Support 让HTML标签上写cla ...

  9. select(有局限性),jq循环添加select的值

    加载的时候改变select的默认值,只需改变select的value值 $("#one").val(@ViewBag.val);//@ViewBag.val是要默认选中的值的val ...

  10. 写C#代码时用到的中文简体字 、繁体字 对应的转化 (收藏吧)

    简体字    下面有与之对应的繁体字 private const String Jian = "啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆疤巴拔跋靶 ...