用线性代数里面的基的思想来解决算法里面的一类亦或问题。
偷了韦神的线性基的板子
以及可以参考的博客线性基详解
感觉查询的时候就是不断的取最高位或者是最低位,用贪心的思想
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| #include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include<climits> #include <algorithm> #include <vector> #include <string> #include <iostream> #include <sstream> #include <map> #include <set> #include <queue> #include <stack> #include <fstream> #include <numeric> #include <stdlib.h> #include <time.h> #include <iomanip> using namespace std; typedef long long ll; const int maxn=1e5+7; struct L_B{ long long d[61],p[61]; int cnt; L_B() { memset(d,0,sizeof(d)); memset(p,0,sizeof(p)); cnt=0; } bool insert(long long val) { for (int i=60;i>=0;i--) if (val&(1LL<<i)) { if (!d[i]) { d[i]=val; break; } val^=d[i]; } return val>0; } long long query_max() { long long ret=0; for (int i=60;i>=0;i--) if ((ret^d[i])>ret) ret^=d[i]; return ret; } long long query_min() { for (int i=0;i<=60;i++) if (d[i]) return d[i]; return 0; } void rebuild() { for (int i=60;i>=0;i--) for (int j=i-1;j>=0;j--) if (d[i]&(1LL<<j)) d[i]^=d[j]; for (int i=0;i<=60;i++) if (d[i]) p[cnt++]=d[i]; } long long kthquery(long long k) { int ret=0; if (k>=(1LL<<cnt)) return -1; for (int i=60;i>=0;i--) if (k&(1LL<<i)) ret^=p[i]; return ret; } }; L_B merge(const L_B &n1,const L_B &n2) { L_B ret=n1; for (int i=60;i>=0;i--) if (n2.d[i]) ret.insert(n2.d[i]); return ret; } int main() { ll i,j,k,f1,f2,f3,f4,t1,t2,t3,t4; L_B a; int n,m; cin >> n; for(i=1;i<=n;i++){ cin >> t1; a.insert(t1); } cout << a.query_max() << endl; a.rebuild(); cout<<a.kthquery(1)<<endl; return 0; }
|
模板题
洛谷
sgu
未解决的问题