HDU3949/AcWing210 XOR (高斯消元求线性基)


求第k小的异或和,用高斯消元求更简单一些。

 1 //用高斯消元求线性基
 2 #include
 3 using namespace std;
 4 #define N 10100
 5 typedef long long ll;
 6 int n;
 7 bool zero;
 8 ll a[N];
 9 
10 void Gauss(){//高斯消元求线性基 
11     int i,k=1;//k标记当前是第几行 
12     ll j=(ll)1<<62;//注意不是63,long long临界2^63-1
13     for(;j;j>>=1){
14         for(i=k;i<=n;i++)
15             if(a[i]&j) break;//找到第j位是1的a[]
16         if(i>n) continue;//没有第j位是1的a[]
17         swap(a[i],a[k]);
18         for(int i=1;i<=n;i++)
19             if(i!=k && a[i]&j) a[i]^=a[k];
20         k++; 
21     } 
22     k--;
23     if(k!=n) zero=true;//有全0的行
24     else zero=false;
25     n=k;//线性基中元素个数 
26 }
27 
28 ll Query(ll k){//第k小异或和 
29     ll ans=0;
30     if(zero) k--;
31     if(!k) return 0;//此时最小异或和就是0 
32     for(int i=n;i;i--){
33         if(k&1) ans^=a[i];
34         k>>=1;
35     }
36     if(k) return -1;//不存在第k小的异或和 
37     return ans;
38 }
39 
40 int main(){
41     int cnt=0;
42     int T;scanf("%d",&T);
43     while(T--){
44         printf("Case #%d:\n",++cnt);
45         scanf("%d",&n);
46         for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
47         Gauss();
48         int q;scanf("%d",&q);
49         while(q--){
50             ll k; scanf("%lld",&k);
51             printf("%lld\n",Query(k));
52         }
53     }
54 }