HDU3949 线性基模板
Posted kgxw0430
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3949 线性基模板相关的知识,希望对你有一定的参考价值。
Ac链接
- 给定n个数,求子集异或和的第k大。(nle10^5,a_ile10^9)。
- 第一步肯定是构造线性基。设线性基的基底数量为k,那么子集异或和本质不同的个数为(2^k)(如果有为0的情况)。其实求第k大很简单,你把k拆分成2进制,对应基底从左到右的每一位,如果为1就异或上去就行了。不过我们需要分为两种情况,一个是存在异或和为0的情况,一个是不存在的。如果不存在异或和为0,需要把k+1。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=100;
ll t,n,m,q,cnt,k,ans,a[N];
void insert(ll v){
for(int i=63;i>=0;--i) if((v>>i)&1){
if(a[i]) v^=a[i];
else{
for(int j=i-1;j>=0;--j)
if((v>>j)&1) v^=a[j];
for(int j=i+1;j<=63;++j)
if((a[j]>>i)&1) a[j]^=v;
a[i]=v;
break;
}
}
}
int main(){
scanf("%lld",&t);
for(int cas=1;cas<=t;++cas){
memset(a,0,sizeof(a));
scanf("%lld",&n);ll x;
for(int i=1;i<=n;++i){
scanf("%lld",&x);
insert(x);
}
cnt=0;
for(int i=0;i<=63;++i) if(a[i]) cnt++;
scanf("%lld",&m);
printf("Case #%d:
",cas);
for(int i=1;i<=m;++i){
scanf("%lld",&k);
if(cnt==n) k++;
ll ans=0;ll tmp=cnt;
if(k>(1LL<<cnt)){printf("-1
");continue;}
for(int i=63;i>=0;--i){
if(a[i]){
ll now=1LL<<(tmp-1);
if(k>now) k-=now,ans^=a[i];
tmp--;
}
}
printf("%lld
",ans);
}
}
return 0;
}
以上是关于HDU3949 线性基模板的主要内容,如果未能解决你的问题,请参考以下文章