BZOJ[2460] [BeiJing2011]元素
通过这个题,新学了一个线性基;
这个东西就是用尽量少的数,使他们之间相互异或时候的值域和原值域相等;
性质:
1.这个东西异或不出来0;
2.当d[n]数组是满的时候,他的值域是[1,(1<<n)-1];
然后就能判断当前的数能不能被之前的数XOR表示出来
然后就把所有的矿石从大到小插入就行了(如果当前最大的与多个集合异或为0,那么舍弃他是没用的,没有留着更优)
1 #include <map> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 # define maxn 1010 9 using namespace std; 10 typedef long long LL; 11 int n; 12 struct node{ 13 LL id; int w; 14 }g[maxn],Num[maxn]; 15 bool cmp1(const node a,const node b){ 16 if(a.id==b.id) return a.w>b.w; 17 return a.id<b.id; 18 } 19 bool cmp2(const node a,const node b){return a.w>b.w;} 20 LL d[65]; 21 bool Insert(LL x){ 22 for(int i=62;i>=0;i--){ 23 if(x&(1ll<<i)){ 24 if(!d[i]){ 25 d[i]=x; 26 break; 27 } 28 else x^=d[i]; 29 } 30 } 31 return x>0; 32 } 33 int main(){ 34 // freopen("a.in","r",stdin); 35 scanf("%d",&n); 36 for(int i=1;i<=n;i++) scanf("%lld%d",&g[i].id,&g[i].w); 37 sort(g+1,g+n+1,cmp1); 38 g[0].id=-1; 39 int ji=0; 40 for(int i=1;i<=n;i++){ 41 if(g[i].id!=g[i-1].id) Num[++ji]=g[i]; 42 } 43 n=ji; 44 sort(Num+1,Num+n+1,cmp2); 45 int ans=0; 46 for(int i=1;i<=n;i++){ 47 if(Insert(Num[i].id)) ans+=Num[i].w; 48 } 49 cout<<ans<<endl; 50 }