元素
元素
题意:
炼制法杖,有编号与权值。
如果在炼制过程中不能使用超过一块同一种矿石,如果给现在发现的每一种矿石进行合理的编号(编号为正整数,称为该矿石的元素序号),那些矿石的元素序号按位异或起来不能为零。
题解:
贪心 + 线性基
学完线性基后这道题就变的很简单了,为啥要写呢?想让线性基有例题。
贪心的将矿石的魔力值从小到大排序,判断能否插入线性基,如果能,答案加上这个矿石的魔力值。
千万不要全部插入之后再判断,根据add
函数的流程,插入了 \(a\),不一定保存 \(a\)。
/*
Date:2021.7.25
Source:luogu 4570
konwledge: 线性基, 贪心,先按魔力值排序
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#define orz cout << "AK IOI"
#define int long long
using namespace std;
const int maxn = 1010;
inline int read()
{
int f = 0, x = 0; char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
return f ? -x : x;
}
inline void print(int X)
{
if(X < 0) {X = ~(X - 1); putchar('-');}
if(X > 9) print(X / 10);
putchar(X % 10 + '0');
}
int n, ans, d[maxn * 3];
struct node{
int num, mag;
}a[maxn];
bool add(int x)
{
for(int i = 62; i >= 0; i--)
{
if(x & (1ll << i))
{
if(d[i]) x ^= d[i];
else {d[i] = x; return 1; break;}
}
}
return 0;
}
bool cmp(node a, node b)
{
return a.mag > b.mag;
}
signed main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n = read();
for(int i = 1; i <= n; i++)
a[i].num = read(), a[i].mag = read();
sort(a + 1, a + n + 1, cmp);
//for(int i = 1; i <= n; i++) add(a[i].num);
for(int i = 1; i <= n; i++)
if(add(a[i].num)) ans += a[i].mag;
print(ans);
return 0;
}