【bzoj 2460 [BeiJing2011]元素】
阿新 • • 發佈:2018-12-01
題意:
相傳,在遠古時期,位於西方大陸的 Magic Land 上,人們已經掌握了用魔
法礦石煉製法杖的技術。那時人們就認識到,一個法杖的法力取決於使用的礦石。
一般地,礦石越多則法力越強,但物極必反:有時,人們為了獲取更強的法力而
使用了很多礦石,卻在煉製過程中發現魔法礦石全部消失了,從而無法煉製
出法杖,這個現象被稱為“魔法抵消” 。特別地,如果在煉製過程中使用超過
一塊同一種礦石,那麼一定會發生“魔法抵消”。
後來,隨著人們認知水平的提高,這個現象得到了很好的解釋。經過了大量
的實驗後,著名法師 Dmitri 發現:如果給現在發現的每一種礦石進行合理的編
號(編號為正整數,稱為該礦石的元素序號),那麼,一個礦石組合會產生“魔
法抵消”當且僅當存在一個非空子集,那些礦石的元素序號按位異或起來
為零。 (如果你不清楚什麼是異或,請參見下一頁的名詞解釋。 )例如,使用兩
個同樣的礦石必將發生“魔法抵消”,因為這兩種礦石的元素序號相同,異或起
來為零。
並且人們有了測定魔力的有效途徑,已經知道了:合成出來的法杖的魔力
等於每一種礦石的法力之和。人們已經測定了現今發現的所有礦石的法力值,
並且通過實驗推算出每一種礦石的元素序號。
現在,給定你以上的礦石資訊,請你來計算一下當時可以煉製出的法杖最多
有多大的魔力。
3
1 10
2 20
3 30
輸出
50
題意懂了就好了,用到了線性基的一個性質,線性基中的每兩個數xor都不會等於0,
然後在貪心的對獲取的能量進行求和,最終就是可以得到的最大值。
#include<bits/stdc++.h> #include <iostream> #include <cmath> #include <cstdio> #include <stdlib.h> #include <ctime> using namespace std; typedef long long ll; typedef pair<int,int> PII; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; const int maxn = 1e6 + 5; ll a[maxn]; struct Point{ll num,val;}point[maxn]; bool operator <(Point a,Point b){return a.val>b.val;} int Build(ll p) { for(int x=63;x>=0;--x) { if(p&(ll(1ll<<x))) { if(!a[x]) { a[x]=p; break; } p^=a[x]; } } if(p) return 1; return 0; } int main() { int n; cin>>n; memset(a,0,sizeof(a)); for(int i=0;i<n;++i) cin>>point[i].num>>point[i].val; sort(point,point+n); ll ans=0; for(int i=0;i<n;++i) if(Build(point[i].num)) ans+=point[i].val; cout<<ans<<endl; return 0; }