元素(HYSBZ-2460)

Problem Description

相传,在远古时期,位于西方大陆的 Magic Land 上,人们已经掌握了用魔法矿石炼制法杖的技术。那时人们就认识到,一个法杖的法力取决于使用的矿石。

一般地,矿石越多则法力越强,但物极必反:有时,人们为了获取更强的法力而使用了很多矿石,却在炼制过程中发现魔法矿石全部消失了,从而无法炼制出法杖,这个现象被称为“魔法抵消” 。特别地,如果在炼制过程中使用超过一块同一种矿石,那么一定会发生“魔法抵消”。 

后来,随着人们认知水平的提高,这个现象得到了很好的解释。经过了大量的实验后,著名法师 Dmitri 发现:如果给现在发现的每一种矿石进行合理的编号(编号为正整数,称为该矿石的元素序号),那么,一个矿石组合会产生“魔法抵消”当且仅当存在一个非空子集,那些矿石的元素序号按位异或起来为零。 (如果你不清楚什么是异或,请参见下一页的名词解释。 )

例如,使用两个同样的矿石必将发生“魔法抵消”,因为这两种矿石的元素序号相同,异或起来为零。

并且人们有了测定魔力的有效途径,已经知道了:合成出来的法杖的魔力等于每一种矿石的法力之和。人们已经测定了现今发现的所有矿石的法力值,并且通过实验推算出每一种矿石的元素序号。 

现在,给定你以上的矿石信息,请你来计算一下当时可以炼制出的法杖最多有多大的魔力。 

Input

第一行包含一个正整数N,表示矿石的种类数。 

接下来 N行,每行两个正整数Numberi 和 Magici,表示这种矿石的元素序号和魔力值。

Output

仅包一行,一个整数:最大的魔力值

Sample Input


1 10 
2 20 
3 30

Sample Output

50

题意:给出 n 个物品,每个物品有两个属性 a、b,现在要在这些物品中取任意个,使得取出的物品中,任意几个物品的属性 a 的异或和不为 0,且 b 的和最大,求最后取出的物品的属性 b 的和

思路:

首先考虑 b 的和最大,显然要按照 b 降序排序来进行取最大的,然后就是要满足 a 的异或和不为 0

考虑线性基的性质,在线性基中,任意基底的异或和不为 0,因此只要能成功添加到线性基中的向量,均满足 a 的异或和不为 0

故而将 b 按降序排序后,将 n 个物品的属性 a 逐个加入线性基中,如果能成功加入到线性基中,就累加 b 的值

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
const int MOD = 1E9+7;
const int N = 1000+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;

struct LinearBasis {
    LL d[60+5];//线性基
    LinearBasis() {
        memset(d,0,sizeof(d));
    }
    bool add(LL x){
        for(int i=60; i>=0; i--)
            if(x&(1LL<<i)) {
                if(d[i])//插入失败,异或
                    x^=d[i];
                else {//插入成功,保存后退出
                    d[i]=x;
                    break;
                }
            }
        return x>0;//x>0插入成功
    }
}lb;
struct Node{
    LL a,b;
    bool operator <(const Node &rhs)const{
        return b>rhs.b;
    }
}node[N];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&node[i].a,&node[i].b);
    sort(node+1,node+1+n);

    LL res=0;
    for(int i=1;i<=n;i++)
        if(lb.add(node[i].a))
            res+=node[i].b;
    printf("%lld\n",res);
    return 0;
}

 

posted @ 2022-09-20 22:51  老程序员111  阅读(245)  评论(0编辑  收藏  举报