题目链接
因为只有位运算,所以可以把每一位分开考虑。
假定初始攻击力的每一位是0或者1,经过所有操作之后的结果。
贪心地从高位到低位选取0/1,尽可能让最终攻击力大即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int res[31][2];
char buf[10];
int rev[31][2]; //让某一位为1,原数中最小为
int n, m;
int main() {
for (int i = 0; i < 31; i++) {
res[i][1] = 1;
}
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
int x = 0;
scanf("%s%d", buf, &x);
for (int j = 0; j < 31; j++) {
if (buf[0] == 'A') {
res[j][0] = res[j][0] & ((x>>j)&1);
res[j][1] = res[j][1] & ((x>>j)&1);
} else if (buf[0] == 'O') {
res[j][0] = res[j][0] | ((x>>j)&1);
res[j][1] = res[j][1] | ((x>>j)&1);
} else if (buf[0] == 'X') {
res[j][0] = res[j][0] ^ ((x>>j)&1);
res[j][1] = res[j][1] ^ ((x>>j)&1);
}
}
}
int ans = 0;
for (int i = 0; i < 31; i++) {
if (res[i][0] && res[i][1]) {
rev[i][1] = 0; rev[i][0] = -1;
} else if (res[i][0] && !res[i][1]) {
rev[i][1] = 0, rev[i][0] = 1;
} else if (!res[i][0] && res[i][1]) {
rev[i][1] = 1, rev[i][0] = 0;
} else {
rev[i][1] = -1, rev[i][0] = 0;
}
}
for (int i = 30; i >= 0; i--) {
if (rev[i][1] >= 0) {
if (rev[i][1] && (1<<i) <= m) {
m -= (1<<i);
ans = ans|(1<<i);
} else if (!rev[i][1]) ans = ans|(1<<i);
}
}
printf("%d\n", ans);
return 0;
}