【模板】【数学】线性基

线性基就是,给你n个数,这n个数会有一个线性基,是的n个数异或的任意值(包括这n个数),都可以用这个线性基来异或出来。

线性基大小logn。

然后可以询问异或最大最小值,以及第k大的值

 

洛谷:https://www.luogu.com.cn/problem/P3812

异或第k大:http://acm.hdu.edu.cn/showproblem.php?pid=3949

【模板】【数学】线性基
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int MN = 61; // 代表最高位数
 5 ll a[200];  // a表示线性基
 6 vector<ll> ra; // ra 是rebuild后的改造后线性基
 7 int n;  //总共插入n个数
 8 //两线性基a,b合并就相当于把所有b[i] (b[i] != 0 ) ins到a里面
 9 void ins( ll x){
10     for(int i = MN;i>=0;--i){
11         if( x & 1ll<<i ){
12             if( a[i] ) x ^= a[i];
13             else{
14                 a[i] = x;
15                 break;
16             }
17         }
18     }
19 }
20 //检查这 n 个数能不能选若干个异或成x(1<=x) (x == 0 的话判断ra大小和n关系)
21 bool check( ll x){
22     for(int i = MN;i>=0;--i){
23         if( x & (1ll << i ) ){
24             if( !a[i] ) return 0;
25             else x ^= a[i];
26         }
27     }
28     return 1;
29 }
30 //异或最大值
31 ll qmax(){
32     ll res = 0;
33     for(int i = 61;i>=0;--i) res = max(res,res^a[i]);
34     return res;
35 }
36 //异或最小值
37 // 如果cnt<n 说明n个数不是相互独立,所以0可以异或表示
38 ll qmin(){
39     int cnt = ra.size();
40     if( cnt < n ) return 0;
41     for(int i = 0;i<=MN;++i) if(a[i]) return a[i];
42 }
43 //构建改后线性基
44 void rebuild(){
45     for(int i = 0;i<=MN;++i){
46         for(int j = i-1;j>=0;--j){
47             if( a[i] & (1ll<<j) ) a[i] ^= a[j];
48         }
49         if(a[i]) ra.push_back( a[i] );
50     }
51 }
52 // 第k小
53 ll query( ll k ){
54     int cnt = ra.size();
55     if( cnt < n ) --k;
56     if(!k) return 0;
57     if( k>= (1ll<<cnt) ) return -1;
58     ll res = 0;
59     for(int i = 0;i<ra.size();++i){
60         if( k & (1ll<<i) ) res ^= ra[i];
61     }
62     return res;
63 }
64 int main(){
65     int T; scanf("%d",&T);
66     for(int cas = 1;cas <= T; ++cas){
67         memset(a,0,sizeof(a));
68         ra.clear();
69         printf("Case #%d:\n",cas);
70         scanf("%d",&n);
71         for(int i = 1;i<=n;++i){
72             ll x; scanf("%lld",&x);
73             ins(x);
74         }
75         rebuild();
76         int m; scanf("%d",&m);
77         while(m--){
78             ll k; scanf("%lld",&k);
79             printf("%lld\n",query(k));
80         }
81     }
82     return 0;
83 }
View Code

 

上一篇:洛谷P4351 [CERC2015]Frightful Formula


下一篇:[AHOI2009]中国象棋