(Zero XOR Subset)-less

题目描述

题解

设前i个数的异或和为\(T_i\)
假设把序列分为\(\{a_1,a_2,···,a_k\},\{a_{k+1},···,a_x\},···,\{a_t,···,a_n\}\)
每个集合的异或和为\(S_1,S_2,···,S_s\)
\(S_1=T_k,S_2=T_x\)^\({T_k},S_i类似\)
这道题让求抽出任意\(S_i\)之间的异或不为0,也就是求出一个极大线性无关组
那么就是线性基
考虑每个\(S_i\)都能被\(T\)数组表示出,那么通过T数组来构造线性基,线性基的大小就为最大划分个数
特殊:如果\(T_n=0\),那么如何构造也不行,则为-1

点击查看代码
#include<functional>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<deque>
#define ll long long 
using namespace std;
const int maxn=5e5+101;
const int MOD=998244353;
const int inf=2147483647;
ll read(){
    ll x=0,f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    return x*f;
}
int zero,n;
struct Lbase{
    ll p[101],d[101];
    int cnt,lens;
    void init(){
        memset(p,0,sizeof(p));
        memset(d,0,sizeof(d));
        cnt=0;lens=0;
    }
    void insert(ll x){//插入
        if(x==0)return ;
        for(int i=lens;i>=0;i--){
            if((1ll<<i)&x){
                if(p[i])x=x^p[i];
                else {p[i]=x;break;}
            }
        }
        return;
    }
    ll mmaxx(){ //查寻最大值
        ll x=0;
        for(int i=lens;i>=0;i--){
            if((x^p[i])>x)x=x^p[i];
        }
        return x;
    }
    bool ask(ll x){ //查寻一个数是否能被异或出来
        for(int i=lens;i>=0;i--){
            if(x&(1ll<<i))x^=p[i];
        }
        return x==0;
    }
    void rebuild(){ //重构
        cnt=0;
        for(int i=lens;i>=0;i--){
            for(int j=i-1;j>=0;j--){
                if(p[i]&(1ll<<j))p[i]^=p[j];
            }
        }
        for(int i=0;i<=lens;i++)if(p[i])d[cnt++]=p[i];
    } 
    void Kth(int pos){  //找第k小
        if(n!=cnt)pos--;//表示可以异或出0
        pos=pos-zero;
        if(pos<=0){printf("0\n");return ;}
        if(pos>=(1ll<<cnt)){printf("-1\n");return ;}
        ll ans=0;
        for(int i=lens;i>=0;i--){
            if(pos&(1ll<<i))ans^=d[i];
        }
        printf("%lld\n",ans);return ;
    }
    void getcnt(){
        for(int i=0;i<=lens;i++)if(p[i])cnt++;
    }
}T;
int main(){
    n=read();ll S=0;T.lens=40;
    for(int i=1;i<=n;i++){
        int x=read();S^=x;
        T.insert(S);
    }
    T.getcnt();
    if(S==0)printf("-1");
    else {printf("%d",T.cnt);}
}
posted @ 2021-11-21 22:31  I_N_V  阅读(31)  评论(0编辑  收藏  举报