1.什么是线性基:
线性基是一个数的集合,并且每个序列都拥有至少一个线性基,取线性基中若干个数异或起来可以得到原序列中的任何一个数。
(异或:相同则为0,不同为1)
(关于异或的小性质:如果a^b^c=0,那么a^b=c,如果a^b=c,则a^c=b)
2.线性基三大性质:
(1)原序列里面的任意一个数都可以由线性基里面的一些数异或得到
(2)线性基里面的任意一些数异或起来都不能得到 0
(3)线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的
(2)线性基里面的任意一些数异或起来都不能得到 0
(3)线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的
试题链接:http://www.acmicpc.sdnu.edu.cn/problem/show/1592 #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <stack> #include <map> #include <set> using namespace std; #define ll long long int n; ll p[60],a[100000]; void insert(ll v) { for(int i=52;i>=0;i--) { if(((1ll<<i)&v)!=0) // 1<<i -> 1左移i位,即2的i次方 // 这句话的意思是:把1转换成long long 类型,然后取(2^i) // &v代表:在二进制中如果有与其不同的,就进行接下来的操作 { if(p[i]) v^=p[i]; else { p[i]=v; return; } } } } int main() { cin >> n; for (int i=1;i<=n;i++) { cin >> a[i]; insert(a[i]); } // for(int i=1;i<=n;++i) scanf("%lld",&a[i]),insert(a[i]); ll ans=0; for(int i=52;i>=0;--i) { if(p[i]) ans = max(ans,ans^p[i]); } // 求完线性基后,贪心求异或最大值,高位数字的贡献要大于它后面所有地位数字的贡献,当前位数上的数异或答案后使得答案更大时,就更新 printf("%lld\n",ans); return 0; }