HDU_3949 XOR 【线性基】

一、题目

  XOR

二、分析

  给定$N$个数,问它的任意子集异或产生的数进行排列,求第K小的数。

  构造出线性基$B$后,如果$|B| < N$,那么代表N个数中有一个数是可以由线性基中的其他数异或出来的,那么相当于可以异或出$0$。也就是说这种情况下会多一个0作为最小数。

  然后对于第$K$大,可以直接对$K$的二进制进行判断,如果为$1$就取线性基对应的数,然后进行异或就可以得出答案了。

三、AC代码

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 #define ll long long
 5 #define Min(a,b) ((a)>(b)?(b):(a))
 6 #define Max(a,b) ((a)>(b)?(a):(b))
 7 const int maxn = 1e4 + 13;
 8 const int maxl = 62;
 9 ll a[maxn];
10 
11 struct LinerBasis
12 {
13     vector<ll> vec;
14     int n;
15 
16     void build(ll *x, int n)
17     {
18         this->n = n;
19         vector<ll> a(maxl+1);
20         for(int i = 1; i <= n; i++)
21         {
22             ll t = x[i];
23             for(int j = maxl; j >= 0; j--)
24             {
25                 if( (t & (1ll<<j)) == 0 )
26                     continue;
27                 if(a[j])
28                     t^=a[j];
29                 else
30                 {
31                     //将低位的已存在的a[k],异或消掉t的这一位1
32                     //a[k]=0也没有影响
33                     for(int k = 0; k < j; k++)
34                     {
35                         if(t & (1ll<<k))
36                             t ^= a[k];
37                     }
38                     //消除高位上a[k]的第j位1
39                     for(int k = j + 1; k <= maxl; k++)
40                     {
41                         if(a[k] & (1ll << j))
42                             a[k] ^= t;
43                     }
44                     a[j] = t;
45                     break;
46                 }
47             }
48         }
49         vec.clear();
50         for(int i = 0; i <= maxl; i++)
51         {
52             if(a[i])
53                 vec.push_back(a[i]);
54         }
55     }
56 
57     ll query(ll K)
58     {
59         //可能异或出0
60         if(vec.size() < n)
61             K--;
62         if(K > (1ll<<vec.size()) - 1)
63             return -1;
64         ll ans = 0;
65         for(int i = 0; i < vec.size(); i++)
66         {
67             if(K & (1ll << i))
68             {
69                 ans ^= vec[i];
70             }
71         }
72         return ans;
73     }
74 
75 }lb;
76 
77 int main()
78 {
79     int T, Case = 0;
80     scanf("%d", &T);
81     while(T--)
82     {
83         int N, Q;
84         scanf("%d", &N);
85         for(int i = 1; i <= N; i++) scanf("%lld", &a[i]);
86 
87         lb.build(a, N);
88 
89         scanf("%d", &Q);
90         ll K;
91         printf("Case #%d:\n", ++Case);
92         while(Q--)
93         {
94             scanf("%lld", &K);
95             printf("%lld\n", lb.query(K));
96         }
97     }
98     return 0;
99 }

猜你喜欢

转载自www.cnblogs.com/dybala21/p/11366699.html