bzoj2460 [BeiJing2011]元素(贪心+线性基)

19 篇文章 0 订阅
8 篇文章 0 订阅

题目链接

分析:
看到有异或和,就可以往线性基上考虑
然而写出线性基之后,在统计答案上卡了

如果直接按照线性基:

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值