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 }
View Code

 

posted @ 2017-10-12 21:10  Nawox  阅读(159)  评论(0编辑  收藏  举报