标签:
简述:n个二元组(a,b),求一个∑b最大,且所有子集XORa<>0的集合
做法:贪心 拟阵证明 线性基
遗传性,子集的子集是自己的子集;交换性,反设2|A|个和覆盖了|B|个元素,那么B中必有子集异或和为零,证毕
拟阵伪代码
Greedy(M,w)
A := 空集;
根据w按非增长顺序对S排序
for 每个x in S根据权w(x)的非增长顺序 do
if (A U {x} belongs to L) then A:=A U {x};
return A;
线性基
字面意思 可以用来判定当前元素能不能用已有的拼出来
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; LL read() { LL x = 0, f = 1;char ch = getchar(); while (ch < ‘0‘ || ch > ‘9‘) f = ch == ‘-‘ ? -1 : 1, ch = getchar(); while (ch >= ‘0‘ && ch <= ‘9‘) x = x * 10 + ch - ‘0‘, ch = getchar(); return x * f; } const int N = 10010; LL lb[65]; struct Q { LL n; int w; }a[N]; bool cmp(const Q& a, const Q& b) { return a.w > b.w; } int main() { freopen("a.in", "r", stdin); int n; n = read(); int ans = 0; for (int i = 1; i <= n; i ++) a[i].n = read(), a[i].w = read(); sort(a + 1, a + 1 + n, cmp); for (int i = 1; i <= n; i ++) { for (int j = 63; j >= 0; j --) { if ((a[i].n >> j) & 1) { if (!lb[j]) { lb[j] = a[i].n; break; } else a[i].n ^= lb[j]; } } if (a[i].n) ans += a[i].w; } printf("%d\n", ans); return 0; }
标签:
原文地址:http://www.cnblogs.com/tellmewtf/p/4538169.html