线性基模板
AcWing 3164. 线性基
由高到低枚举二进制的每一位
通过高斯消元化为上三角矩阵
后将所有元素异或即可
#include
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N];
signed main() {
cin >> n;
for (int i = 0; i < n; i ++ ) cin >> a[i];
int k = 0;
for (int i = 62; i >= 0; i -- ) {
for (int j = k; j < n; j ++ ) {
if (a[j] >> i & 1) {
swap(a[j], a[k]);
break;
}
}
if (!(a[k] >> i & 1)) continue;
for (int j = 0; j < n; j ++ )
if (j != k && (a[j] >> i & 1))
a[j] ^= a[k];
k ++;
if (k == n) break;
}
int res = 0;
for (int i = 0; i < k; i ++ ) res ^= a[i];
cout << res << endl;
return 0;
}
AcWing 210. 异或运算
本题是上面一题的扩展,需要求第\(k\)小的数
先计算线性基
将得到的x个线性基的基底看作二进制的每一位,得到k的二进制表示
(注意判断得到的线性基是线性相关的还是线性无关的)
#include
#define int long long
using namespace std;
const int N = 1e5 + 10;
int T, n, m;
int a[N];
signed main() {
scanf("%lld", &T);
for (int o = 1; o <= T; o ++ ) {
scanf("%lld", &n);
for (int i = 0; i < n; i ++ ) scanf("%lld", &a[i]);
int k = 0;
for (int i = 62; i >= 0; i -- ) {
for (int j = k; j < n; j ++ ) {
if (a[j] >> i & 1) {
swap(a[j], a[k]);
break;
}
}
if (!(a[k] >> i & 1)) continue;
for (int j = 0; j < n; j ++ )
if (j != k && (a[j] >> i & 1))
a[j] ^= a[k];
k ++;
if (k == n) break;
}
reverse(a, a + k);
printf("Case #%d:\n", o);
scanf("%lld", &m);
while (m -- ) {
int x;
scanf("%lld", &x);
if (k < n) x --;
if (x >= (1LL << k)) puts("-1");
else {
int res = 0;
for(int i = 0; i < k; i ++ )
if (x >> i & 1)
res ^= a[i];
printf("%lld\n", res);
}
}
}
return 0;
}