题面
分析
思考什么情况可以装,如果一个数或进去不超过 m m m 就可以加入,否则不能加入,那么如果某一个数和 m m m 或运算能够分为两部分,前一部分进行或运算为 m m m 的子集,后一部分可以是任何数,存在当前一位为 0 0 0,但 m m m 的这一位为 1 1 1,呢么无论如何他都是小于 m m m 的,就一定可以加进去,所以可以枚举所有 m m m 的二进制位,如果当前这一位为 1 1 1,那么可以去枚举所有的物品,如果满足当前位前面为 m m m 对应部分子集,当前位为 0 0 0 ,那么可以加进去,对所有情况取最大值。
代码
#include <bits/stdc++.h>using namespace std;
using ll = long long;const int N = 1e5 + 10;int v[N], w[N];void solve() {int n, m;cin >> n >> m;for(int i = 1; i <= n; i ++) cin >> w[i] >> v[i];ll ans = 0;for(int i = 0; i <= 30; i ++) {if(((m >> i) & 1) || i == 0) {int x = (1 << i) - 1;int res = m | x;ll sum = 0;//cout << i << endl;for(int j = 1; j <= n; j ++) {if(((v[j] >> i) & 1) && i != 0) continue;//cout << v[j] << ' ' << (v[j] | res) << endl;if((v[j] | res) == res) sum += w[j];}//cout << sum << ' ';ans = max(ans, sum);}}cout << ans << "\n";
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int T;cin >> T;while(T --) {solve();}
}