线性基巧妙的一批
线性基的插入看起来很玄学,就随便说几句好了
inline int ins(LL x) {
for(re int j=63;j>=0;--j) {
if(!(x>>j&1)) continue;
if(!lb[j]) {lb[j]=x;return 1;}
x^=lb[j];
}
return 0;
}
上面那个\(x\)异或上\(lb[j]\)其实就是把这一位干掉,把我们要插入的这个数变成异或后的值,如果最后异或的结果是\(0\),那么就说明这个数已经可以被线性基表示出来了
那么表示这个数的线性基中的几个元素也一定会可以表示一些其他的元素,所以这个元素就能被之前的数表示出来
所以排序一下之后一个一个插入就行了
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 1005
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline LL read() {
LL x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int n;
struct Node{LL x;int w;}a[maxn];
inline int cmp(Node A,Node B) {return A.w>B.w;}
LL lb[66];
inline int ins(LL x) {
for(re int j=63;j>=0;--j) {
if(!(x>>j&1)) continue;
if(!lb[j]) {lb[j]=x;return 1;}
x^=lb[j];
}
return 0;
}
int main()
{
n=read();
for(re int i=1;i<=n;i++) a[i].x=read(),a[i].w=read();
std::sort(a+1,a+n+1,cmp);
int ans=0;
for(re int i=1;i<=n;i++) if(ins(a[i].x)) ans+=a[i].w;
printf("%d\n",ans);
return 0;
}