起床困难综合症

原题链接


题目描述

\([0, m]\)中找一个数,在经过\(n\)次位运算之后得到的值最大,求这个最大的值。

输入样例

3 10
AND 5
OR 6
XOR 7

输出样例

1

思路

首先,我们知道位运算是不存在进位的,所以一个位置上填1或0与其他的位置是无关的。
有了以上的结论,我们可以把问题简化成枚举一个数它的每一位是否可以填1
如果一个位置上可以填1,这个位置必须满足以下两个条件:

1.填上1之后,这个数不会超过m
2.填上1之后,经过n次位运算,结果比填上0要大,假如填上0和填上1相同,我们必然要优先填0。
  因为填上0下面的位置更有可能填1而不超过m。

代码实现

#include <iostream>
using namespace std;

const int N = 1e5 + 10;

pair<string, int> a[N];
int n, m;

int calc(int bit, int now){
	for(int i = 0; i < n; i++){
		int x = a[i].second >> bit & 1;
		if(a[i].first == "AND") now &= x;
		if(a[i].first == "OR") now |= x;
		if(a[i].first == "XOR") now ^= x;
	}
	return now;
}
int main(){
	cin >> n >> m;
	for(int i = 0; i < n; i++) cin >> a[i].first >> a[i].second;
	int ans = 0, val = 0;
	for(int bit = 29; bit >= 0; bit--){
		int res0 = calc(bit, 0);
		int res1 = calc(bit, 1);
		if(val + (1 << bit) <= m && res0 < res1)
			val += 1 << bit, ans += 1 << bit;
		else ans += res0 << bit;
	}
	cout << ans << endl;
	return 0;
}