題目:
給定n個礦石的編號和魔力值,讓你選出一些礦石,這些礦石的id異或起來不能是0,而且總的魔力值最大,輸出最大的魔力值
Input
第一行包含一個正整數N,表示礦石的種類數。
接下來 N行,每行兩個正整數Numberi 和 Magici,表示這種礦石的元素序號和魔力值。
對於全部的數據:N ≤ 1000,Numberi ≤ 10^18,Magici ≤ 10^4。
Output
僅包一行,一個整數:最大的魔力值
Sample Input
3
1 10
2 20
3 30
Sample Output
50
解題思路:
看到XOR一般就要想到線性基,這裏只需要用到最基礎的線性基即可,不需要求異或出來的第k小的數
一般的線性基模版每當p[j]已經有數時,a[i]^=p[j],直到a[i]可以填入,這樣的話實際上最後能填入的那個非零的a[i]是由多個原a[i]異或出來的。
將礦石的屬性存入結構體數組中,按照魔力值從大到小排序,從魔力值大的礦石開始遍歷,用其id構造行階梯矩陣,如果可以填入(最終異或得到的a[i].id不爲0),說明最初的a[i].id與之前選定的礦石中的部分礦石的a[i].id異或起來不爲0,將其value值加入結果中,且整個行階梯矩陣本身就線性無關的,異或起來非0。這樣根據貪心的思想,最終結果記錄的就是最大的魔力值。
ac代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000+10;
const int max_base=60;
struct node{
ll id;
ll value;
friend bool operator <(node a,node b)
{
return a.value>b.value;
}
}a[maxn];
ll n,p[max_base+3];
ll solve()
{
ll ans=0;
for(int i=0;i<n;i++)
{
for(int j=max_base;j>=0;j--)
{
if(a[i].id>>j&1)
{
if(p[j])
a[i].id^=p[j];
else
{
p[j]=a[i].id;
break;
}
}
}
if(a[i].id)
ans+=a[i].value;
}
return ans;
}
int main()
{
scanf("%lld",&n);
for(int i=0;i<n;i++)
scanf("%lld %lld",&a[i].id,&a[i].value);
sort(a,a+n);
printf("%lld\n",solve());
return 0;
}