有 (n) 个物品,每个物品有两个属性 (a_i,b_i) ,挑选出若干物品,使得这些物品 (a_i) 的异或和 (x le m).问在这一限制下,(b_i) 的总和最大可能为多少.
输入
输入文件名为xor.in。
第一行两个数 (n,m (n le 32))
接下来n行每行两个数 (a_i) 和 (b_i)
输出
输出文件名为xor.out。
一个数表示答案
样例输入
4 5
1 2
2 1
3 3
4 1
样例输出
7
提示
【数据说明】
对于30%的数据,$1 le n le 20,1 le a_i , m<2^{30} $
对于另外30%的数据,$1 le n le 32,1 le a_i , m < 2^{18} $
对于100%的数据,(1 le n le 32,1 le a_i , m < 2^{30},b[i] le 10^6)
本来我又以为是个神仙DP.....比如什么EX背包啊啥的
但是转眼一看数据范围—— (meet : in : the : middle) 啊
但是我不想写,于是就写了一个彻彻底底的爆搜!
然后....然后就A了,爆搜也没什么好讲的,直接上代码吧:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#define ll long long
#define max(a,b) (a>b?a:b)
const ll N = 40;
struct things{ll weight,value;}t[N];
ll ans,sum[N],n,m;
inline bool cmp(const things&a,const things&b){return a.value > b.value;}
inline void dfs(ll wet,ll val,ll step){
if(wet <= m) ans = max(ans,val);
if(step >= n + 1) return ;
if(sum[step] + val <= ans) return ;
dfs(wet ^ t[step].weight , val + t[step].value , step + 1);
dfs(wet , val , step + 1);
return ;
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i = 1 ; i <= n ; ++ i) scanf("%lld%lld",&t[i].weight,&t[i].value);
std::sort(t + 1 , t + n + 1 , cmp);
for(int i = n ; i >= 1 ; -- i) sum[i] = sum[i + 1] + t[i].value;
dfs(0,0,1);printf("%lld
",ans);
return 0;
}