title: 起床困难综合症
date: 2023-12-07 18:53:24
tags: 二进制状态压缩
categories: 算法竞赛
题目链接
− − > --> −−> 传送门
题目大意
d r d drd drd 的防御战线由 n n n 扇防御门组成。
每扇防御门包括一个运算 o p op op 和一个参数 t t t,其中运算一定是 O R , X O R , A N D OR,XOR,AND OR,XOR,AND 中的一种,参数则一定为非负整数。如果还未通过防御门时攻击力为 x x x,则其通过这扇防御门后攻击力将变为 x x x o p op op t t t。
最终 d r d drd drd 受到的伤害为对方初始攻击力 x x x 依次经过所有 n n n 扇防御门后转变得到的攻击力。
由于 a t m atm atm 水平有限,他的初始攻击力只能为 0 0 0 到 m m m 之间的一个整数(即他的初始攻击力只能在 0 , 1 , … , m 0,1,…,m 0,1,…,m 中任选,但在通过防御门之后的攻击力不受 m m m 的限制)。
为了节省体力,他希望通过选择合适的初始攻击力使得他的攻击能让 d r d drd drd 受到最大的伤害,请你帮他计算一下,他的一次攻击最多能使 d r d drd drd 受到多少伤害。
输入样例
3 3 3 10 10 10
A N D AND AND 5 5 5
O R OR OR 6 6 6
X O R XOR XOR 7 7 7
输出样例
1 1 1
思路
位运算的主要特点之一就是在二进制表示下不进位,因此,每一位是否为 1 1 1 是独立的。 a n s ans ans 的第 k k k 位只与 x o x_o xo 的第 k k k 位有关。
由此,我们从高位到低位依次考虑每一位填 1 1 1 还是 0 0 0。
这相当于在 m m m 范围内造出一个符合条件的最大数字 a n s ans ans,这就要 a n s ans ans 的每一位尽可能的为 1 1 1。而满足填 1 1 1 的条件则是,已经填好更高位构成的数值加上当前第 k k k 位的 1 < < k 1 << k 1<<k 不超过 m m m,同时当前位置放 1 1 1 的贡献大于放 0 0 0 的
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
pair<string,int> a[N];
int m,n;
int cal(int bit,int now)
{
for(int i = 1; i <= n ; i ++){
int x = a[i].second >> bit & 1;
string str = a[i].first;
if(str == "AND") now &= x;
else if(str == "OR") now |= x;
else now ^= x;
}
return now;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++){
string s;int x;
cin >> s >> x;
a[i] = {s,x};
}
int val = 0,ans = 0;
for(int i = 29; i >= 0 ; i --){
int res1 = cal(i,1),res0 = cal(i,0);
if(val + (1 << i) <= m && res0 < res1){
ans += res1 << i,val += 1 << i;
}
else ans += res0 << i;
}
cout << ans << endl;
return 0;
}