[hdu3949]XOR(线性基求xor第k小)

题目大意:求xor所有值的第k小,线性基模板题。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const int MAX_BASE=63;
ll base[64],a[10006],n,m;
//构造线性基,也可用来判断x是否存在,最后返回是否等于0即可。
void getbase(){
  memset(base,0,sizeof base);
  for(int i=1;i<=n;i++){
      for(int j=MAX_BASE;j>=0;j--){
          if(a[i]>>j){
              if(!base[j]){
                base[j]=a[i];
                break;
              }
              a[i]^=base[j];
          }
      }
  }
}
//从高位到低位扫描线性基。如果异或之后答案变大,就把这一位异或到答案。
ll query_max(){
  ll ans=0;
  for(int i=MAX_BASE;i>=0;i--){
      if((base[i]^ans)>ans){
          ans=base[i]^ans;
      }
  }
  return ans;
}
//从低位到高位扫描线性基。最低位上的线性基即为答案。
ll query_min(){
  for(int i=0;i<=MAX_BASE;i++)
      if(base[i]>0) return a[i];
}
ll cnt,p[64];
//注意0的特殊情况,判断if(n!=cnt)k--;
void rebuild(){
  cnt=0;
  for(int i=MAX_BASE;i>=0;i--){
    if(!base[i]) continue;
    for(int j=i-1;j>=0;j--)//还是倒序,一定
      if((base[i]>>j)&1)
        base[i]^=base[j];
  }
  for(int i=0;i<=MAX_BASE;i++)
    if(base[i])
      p[cnt++]=base[i];
}
ll query_k_max(ll k){
  ll ans=0;
  if(k>=(1ll<<cnt)) return -1;
  for(int i=MAX_BASE;i>=0;i--){
    if((k>>i)&1)
      ans^=p[i];
  }
  return ans;
}

int main(){
  int t,tmp;
  scanf("%d",&t);
  for(int _=1;_<=t;_++){
    printf("Case #%d:\n",_);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    getbase();
    rebuild();
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
      scanf("%d",&tmp);
      if(n!=cnt) tmp--;
      ll ans=query_k_max(tmp);
      printf("%lld\n",ans);
    }
  }
  return 0;
}

 

posted @ 2019-02-10 00:58  Elpsywk  阅读(234)  评论(0编辑  收藏  举报