k<=100
才学了拟阵,然后现学现用,居然就发现了这么一道拟阵好题。
题目简化出来大概是你要在一堆数集中,删除一些数,使得剩下的数不可能组成异或和为0的非空集合,并且使删除的数尽量的小。考虑依次加数,每次加完异或高消一次,如果发现线性相关,那么就不加入这个数,否则加入。这样可以满足删除的数的个数尽量小。
然而题目中求得是删除的数字的和,怎么办?注意到这道题所说的“子集异或和非0集合”其实就是一个拟阵。【拟阵(E,I)1.空集满足 2.若集合A满足,则A子集满足“子集异或和非0” 3.若card(A)>card(B),存在x属于A,且B+{x}属于I,这个可以用异或高消来理解】所以按照拟阵的标准贪心思路,将读入的数列从大到小排一遍序就ok了。
发现以前写的异或高消都有bug,整个人都splay起来了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 100000 typedef long long qword; int lst[MAXN]; inline bool cc(int x,int y) { for (int i=30;i>=0;i--) if (x&(1<<i)) return y&(1<<i); } int main() { freopen("input.txt","r",stdin); int n; scanf("%d",&n); for (int i=0;i<n;i++) scanf("%d",lst+i); sort(lst,lst+n,greater<int>()); qword ans=0; int x,y; for (int i=0;i<n;i++) { x=lst[i]; for (int j=0;j<i;j++) { if (cc(lst[j],lst[i])) lst[i]^=lst[j]; } if (!lst[i]) ans+=x; } printf("%lld\n",ans); }
转载于:https://www.cnblogs.com/mhy12345/p/4523329.html