您的位置:首页 > 其它

BZOJ 2460 元素 线性基+贪心

2017-09-21 10:32 393 查看
线性基是一种特殊的基,它通常会在异或运算中出现,它的意义是:通过原集合S的某一个最小子集S1使得S1内元素相互异或得到的值域与原集合S相互异或得到的值域相同。

性质:

线性基能相互异或得到原集合的所有相互异或得到的值。

线性基是满足性质1的最小的集合

线性基没有异或和为0的子集。

题意:n个矿石,第i个矿石有编号num[i]和价值val[i] num[i]<=1e18,val[i]<=1e4,n<=1e3.

问从n个中选出若干个矿石,在这些矿石编号num[i]异或和不为0的情况下,其价值和最大为多少

选出子集的异或和不为0 马上想到线性基,然后贪心将val从大到小排序后,构造线性基即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+20;
const ll inf=2e16;
struct node{
ll num,val;
}a
;
bool cmp(node a,node b)
{
return a.val>b.val;
}
ll mk[110];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
cin>>a[i].num>>a[i].val;
sort(a+1,a+1+n,cmp);
memset(mk,0,sizeof(mk));
ll ans=0;
for(int i=1;i<=n;i++)
{
ll x=a[i].num;
for(ll j=63;j>=0;j--)
{
if(((x>>j)&1)==0)	continue;
if(!mk[j])
{
mk[j]=x;
break;
}
x^=mk[j];//Èô×îºóx==0 Ôò˵Ã÷x¿ÉÒÔͨ¹ýÆäËûÊýÒì»ò³öÀ´.
}
if(x)
ans+=a[i].val;
}
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: