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 阅读(...) 评论(...) 编辑 收藏