分析:
看到有异或和,就可以往线性基上考虑
然而写出线性基之后,在统计答案上卡了
如果直接按照线性基:
for (int i=30;i>=0;i--)
if (b[i])
ans+=v[b[i]];
这样统计出的答案保证了编号的异或值最大,与题设不符,非常不符
原来这道题的核心是贪心啊
我们按照v排序
从大到小插入元素维护线性基
因为我们不关心最后的异或和是多少,所以简单写法就好了
tip
计算的时候注意强制类型转换(1<< j得到的是int,而1LL<< j得到的是ll)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1005;
struct node{
ll x,v;
bool operator <(const node &a) const {
return v>a.v;
}
};
node a[N];
ll b[100];
int n;
void cal() {
ll ans=0;
int i,j;
for (i=1;i<=n;i++)
for (j=63;j>=0;j--)
if (a[i].x&(1LL<<j)) { //1LL<<j
if (b[j]) a[i].x^=b[j];
else {
b[j]=a[i].x; //选中
ans+=a[i].v;
break;
}
}
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lld%lld",&a[i].x,&a[i].v);
sort(a+1,a+1+n);
cal();
return 0;
}