LOJ114 k大(xiao)异或和(线性基)

  构造线性基后将其消至对任意位至多只有一个元素该位为1。于是就可以贪心了,将k拆成二进制就好。注意check一下是否能异或出0。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100010
#define ll long long
ll read()
{
    ll x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
bool flag=0;
ll n,m,base[51],s;
int main()
{
    freopen("kxor.in","r",stdin);
    freopen("kxor.out","w",stdout);
    n=read();
    for (int i=1;i<=n;i++)
    {
        ll x=read();
        for (int j=50;~j;j--)
        if (x&(1ll<<j))
            if (!base[j]) {base[j]=x;break;}
            else x^=base[j];
        if (!x) flag=1;
    }
    for (int i=50;~i;i--)
    if (base[i])
    {
        s++;
        for (int j=i-1;~j;j--)
        if (base[i]&(1ll<<j)) base[i]^=base[j];
    }
    s=1ll<<s;
    m=read();
    for (int i=1;i<=m;i++)
    {
        ll k=read()-flag;
        if (k>=s) printf("-1
");
        else
        {
            ll ans=0;
            for (int j=0;j<=50;j++)
            if (base[j])
            {
                ans^=(k&1)*base[j];
                k>>=1;
            }
            printf("%lld
",ans);
        }
    }
    fclose(stdin);fclose(stdout);
    return 0;
}
原文地址:https://www.cnblogs.com/Gloid/p/9383999.html