题目大意: 有 n n n 个东西,每个东西能选当且仅当它的元素序号不能通过之前选过的东西的元素序号异或得到,在此前提下,求魔力的最大值。
题解
如果没看过我写的关于线性基的博客,请先阅读一下吧,特别是理解其中的第三条性质。
根据这条性质,我们可以知道,一个序列,能够插入到线性基里面的元素是一定的,那么既然只能插那么多个,显然优先插魔力值大的进去呀!
可能有人会问,如果有三个数 a , b , c ( a < b < c ) a,b,c(a<b<c) a,b,c(a<b<c),先插入 c c c导致 a a a和 b b b都不能插入,但是 a + b > c a+b>c a+b>c,如果先将 a , b a,b a,b插入到线性基里面,那么得到的值的和不是更大吗?
是会更大,但是这种情况不存在。(没想到吧)
仔细想想,假如插入了 c c c 之后会导致 a , b a,b a,b 不能插入,那么插入了 a a a 或 b b b 后也肯定会导致另外两个不能插入。
所以,按这种贪心的做法得到的一定是最优的,不可能因为一个元素而导致多个元素不能插入,就算去掉这个元素,也只能插入那多个元素中的一个。
代码就很简单了:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
struct node{ll x;int y;};
node a[1010];
int n,ans=0;
ll d[70];
bool cmp(node x,node y){return x.y>y.y;}
bool add(ll x)
{
for(int i=62;i>=0;i--)
{
if(x&(1ll<<i))
{
if(!d[i])
{
d[i]=x;
return true;
}
else x^=d[i];
}
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld %d",&a[i].x,&a[i].y);
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
if(add(a[i].x))ans+=a[i].y;
printf("%d",ans);
}