1. 程式人生 > >Bzoj 2460: [BeiJing2011]元素

Bzoj 2460: [BeiJing2011]元素

後來 nod 插入 str style 石頭 線性 string print

Description

相傳,在遠古時期,位於西方大陸的 Magic Land 上,人們已經掌握了用魔法礦石煉制法杖的技術。那時人們就認識到,一個法杖的法力取決於使用的礦石。一般地,礦石越多則法力越強,但物極必反:有時,人們為了獲取更強的法力而使用了很多礦石,卻在煉制過程中發現魔法礦石全部消失了,從而無法煉制出法杖,這個現象被稱為“魔法抵消” 。特別地,如果在煉制過程中使用超過一塊同一種礦石,那麽一定會發生“魔法抵消”。

後來,隨著人們認知水平的提高,這個現象得到了很好的解釋。經過了大量的實驗後,著名法師 Dmitri 發現:如果給現在發現的每一種礦石進行合理的編號(編號為正整數,稱為該礦石的元素序號),那麽,一個礦石組合會產生“魔法抵消”當且僅當存在一個非空子集,那些礦石的元素序號按位異或起來為零。 (如果你不清楚什麽是異或,請參見下一頁的名詞解釋。 )例如,使用兩個同樣的礦石必將發生“魔法抵消”,因為這兩種礦石的元素序號相同,異或起來為零。

並且人們有了測定魔力的有效途徑,已經知道了:合成出來的法杖的魔力等於每一種礦石的法力之和。人們已經測定了現今發現的所有礦石的法力值,並且通過實驗推算出每一種礦石的元素序號。

現在,給定你以上的礦石信息,請你來計算一下當時可以煉制出的法杖最多有多大的魔力。

Input

第一行包含一個正整數N,表示礦石的種類數。 接下來 N行,每行兩個正整數Numberi 和 Magici,表示這種礦石的元素序號和魔力值。

Output

僅包一行,一個整數:最大的魔力值

Sample Input

3

1 10

2 20

3 30

Sample Output

50

題面好長...大概題意,給一些石頭,每個石頭有編號和價值,選出一些石頭,使得這些石頭的編號異或和不為0(也不能有任何一個子集異或和為0),求出最大的石頭價值總和。

這道題...線性基裸題...大概就是先排序,把價值大的優先插入線性基,並且同時將價值累加進答案,就是貪心的過程。

直接貼代碼:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 using namespace std;
 7 struct node{
 8     long long num;
 9     int val;
10     friend bool operator
<(const node &a,const node &b){ 11 return a.val>b.val; 12 } 13 }in[1010]; 14 long long a[70]; 15 int main() 16 { 17 int n,i,j,ans=0; 18 scanf("%d",&n); 19 for(i=1;i<=n;i++) scanf("%lld%d",&in[i].num,&in[i].val); 20 sort(in+1,in+n+1); 21 for(i=1;i<=n;i++){ 22 for(j=63;j>=0;j--){ 23 if((in[i].num&(1ll<<j))==0) continue; 24 if(a[j]==0ll){ 25 a[j]=in[i].num; 26 ans+=in[i].val; 27 break; 28 } 29 in[i].num^=a[j]; 30 } 31 } 32 printf("%d",ans); 33 return 0; 34 }

Bzoj 2460: [BeiJing2011]元素