题解P4570 [BJWC2011]元素 - 线性基 - 贪心
Posted bn_ff
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解P4570 [BJWC2011]元素 - 线性基 - 贪心相关的知识,希望对你有一定的参考价值。
P4570 [BJWC2011]元素
声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论???(ˊ?ˋ)??*?
题目描述
给你 (n) 个二元组 ((x, y)),从中选取任意个,构成集合 (S),其中不允许存在某个 (S) 的子集中的 (x_i) 异或起来为 (0)。求 (sum_{iin S} y_i) 的最大值
输入格式
第一行包含一个正整数 (N),表示二元组个数。
接下来 (N) 行,每行两个正整数 (x_i,y_i)。
输出格式
仅包含一行,一个整数代表最大的答案。
(\)
(\)
(Solution)
这道题分两步,先按照大小排序,再用线性基加数
(1st step)
引入一个关于异或的性质:若 (x ext{^} y = z),则 (x ext{^} z = y , y ext{^} z = x)
假设现在想往集合里加 (x_0),但是加不了了
那么集合里就有 (x_1 ext{^} x_2 ext{^} ... ext{^} x_i = x_0)
对于这些选出来的二元组,若 (y_j < y_0),又因为 (x_1 ext{^} x_2 ext{^} ... ext{^} x_i ext{^} x_0 = x_j),所以可以把 (j) 换成 (i),情况没变,但对答案贡献更大
所以可以贪心,按照 (y_i) 的从大到小排
(2nd step)
线性基有一个性质:线性基里不存在某些数异或起来等于 (0)
关于证明
如果有 (x_1, x_2, x_3...x_i) 在线性基里,且异或起来等于 (0),则 (x_i = x_1 ext{^} x_2 ext{^} ... ext{^} x_{i-1}),那么 (x_i) 可以用这些数异或表示出来,不可能加入进线性基里(根据线性基的定义)
所以只要能插入进线性基,则可行
完结撒花??ヽ(°▽°)ノ?
(\)
(\)
(Code)
#include<bits/stdc++.h>
#define ll long long
#define F(i, x, y) for(int i = x; i <= y; ++i)
using namespace std;
ll read();
const int N = 1e3 + 5;
ll n, p[70], ans;
struct node{
ll x, y;
}a[N];
bool cmp(node x, node y){return x.y > y.y;}
bool solve(ll x)
{
for(int i = 63; i; -- i)
if((x >> i - 1) & 1)
if(! p[i])
{
p[i] = x;
return true;
}
else x ^= p[i];
return false;
}
int main()
{
n = read();
F(i, 1, n) a[i].x = read(), a[i].y = read();
sort(a + 1, a + 1 + n, cmp);
F(i, 1, n) if(solve(a[i].x)) ans += a[i].y;
printf("%lld", ans);
return 0;
}
ll read()
{
ll x = 0, f = 1;
char c = getchar();
while(c < ‘0‘ || c > ‘9‘) {if(c == ‘-‘) f = -1; c = getchar();}
while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
return x * f;
}
以上是关于题解P4570 [BJWC2011]元素 - 线性基 - 贪心的主要内容,如果未能解决你的问题,请参考以下文章