数学-线性基
设原集为S,线性基为P,若|S|>|P|,则异或会出现0。若|P|==n,则会产生2^n个不同数(包括0)
而线性基不包含0元素,故若|S|中元素可以异或出0,k需要自减
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+10;
ll a[N],d[64],t[64];//注意:2的六十次方大于1e18
void solve()
{
memset(d,0,sizeof d);
memset(t,0,sizeof t);
int n;
bool flag=0;//flag表示是否存在数为0
cin>>n;
for(int i=0;i<n;++i)
{
cin>>a[i];
ll x=a[i];
for(int j=61;j>=0;--j)
{
if((x>>j)&1)
{
if(!d[j]) {d[j]=x;break;}//注意:如果此处d[j]等于x需要break掉,不能继续循环
else x^=d[j];
}
}
}
for(int i=0;i<=61;++i)
{
for(int j=i+1;j<=61;++j)
{
if(d[j]>>i&1) d[j]^=d[i];
}
}
int cnt=0;
for(int i=0;i<=61;++i) if(d[i]) t[cnt++]=d[i];
if(cnt<n) flag=1;
int q;
ll k;
cin>>q;
for(int i=0;i<q;++i)
{
cin>>k;
ll ans=0;
if(flag) k--;
if(k>=(1ll<<cnt))
{
cout<<"-1"<<'\n';continue;
}
for(int j=0;j<=61;++j)
{
if(k>>j&1) ans^=t[j];
}
cout<<ans<<'\n';
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
for(int i=1;i<=T;++i)
{
cout<<"Case #"<<i<<':'<<'\n';
solve();
}
}