(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);}
}