LOJ #6060. 「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set

有趣的思博套路题,想到了基本上加上个对线性基的理解就可以过了

首先考虑到这个把数分成两半的分别异或的过程不会改变某一位上\(1\)的总个数

因此我们求出所有数的\(\operatorname{xor}\),然后从高到低枚举每一位的值,分情况讨论:

  • 如果这一位是\(1\),那么显然分配完后必然使得\(x_1,x_2\)中一个是\(0\),一个是\(1\)
  • 如果这一位是\(0\),如果不是全\(0\),那么必然可以构造方案让\(x_1,x_2\)两数都是\(1\)

比较一下我们优先使\(x_1+x_2\)最大,因此如果这一位是\(0\)就应该优先考虑

子集异或和最大怎么做,直接套线性基即可,这里其实就是改了下插入的优先级,让\(0\)位的先插入

求出\(x_1+x_2\)的最大值后我们尽量把\(1\)位上的\(1\)分给\(x_2\)即可,继续从高位到低位在线性基上查即可

CODE

#include<cstdio>
#include<cctype>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
const int N=100005;
typedef long long LL;
int n; LL a[N],xrs;
class FileInputOutput
{
	private:
		static const int S=1<<21;
		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
		char Fin[S],*A,*B;
	public:
		Tp inline void read(T& x)
		{
			x=0; char ch; while (!isdigit(ch=tc()));
			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
		}
		#undef tc
}F;
class Linear_Base
{
	private:
		static const int R=60;
		LL bit[R+5];
	public:
		inline void insert(LL x)
		{
			RI i; for (i=R;~i;--i) if (!((xrs>>i)&1)&&((x>>i)&1))
			{
				if (!bit[i]) { bit[i]=x; return; } x^=bit[i];
			}
			for (i=R;~i;--i) if ((xrs>>i)&1&&((x>>i)&1))
			{
				if (!bit[i]) { bit[i]=x; return; } x^=bit[i];
			}
		}
		inline LL query(LL ans=0)
		{
			RI i; for (i=R;~i;--i) if (!((xrs>>i)&1)&&!((ans>>i)&1)) ans^=bit[i];
			for (i=R;~i;--i) if (((xrs>>i)&1)&&((ans>>i)&1)) ans^=bit[i]; return ans;
		}
}LB;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (F.read(n),i=1;i<=n;++i) F.read(a[i]),xrs^=a[i];
	for (i=1;i<=n;++i) LB.insert(a[i]); return printf("%lld",LB.query()),0;
}
posted @ 2019-04-16 21:19  hl666  阅读(...)  评论(...编辑  收藏