链接:https://ac.nowcoder.com/acm/contest/996/E
来源:牛客网
题目描述
21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳。作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争。通过研究相关文献,他找到了该病的发病原因:在深邃的太平洋海底中,出现了一条名为 drd 的巨龙,它掌握着睡眠之精髓,能随意延长大家的睡眠时间。正是由于 drd 的活动,起床困难综合症愈演愈烈,以惊人的速度在世界上传播。为了彻底消灭这种病,atm 决定前往海底,消灭这条恶龙。
历经千辛万苦,atm 终于来到了 drd 所在的地方,准备与其展开艰苦卓绝的战斗。drd 有着十分特殊的技能,他的防御战线能够使用一定的运算来改变他受到的伤害。具体说来,drd 的防御战线由 𝑛 扇防御门组成。每扇防御门包括一个运算 op 和一个参数 𝑡,其中运算一定是 OR,XOR,AND 中的一种,参数则一定为非负整数。如果还未通过防御门时攻击力为 𝑥 ,则其通过这扇防御门后攻击力将变为 𝑥 op 𝑡 。最终drd 受到的伤害为对方初始攻击力 𝑥 依次经过所有 𝒏 扇防御门后转变得到的攻击力。
由于atm 水平有限,他的初始攻击力只能为 0 到 𝑚 之间的一个整数(即他的初始攻击力只能在 0, 1, … , 𝑚 中任选,但在通过防御门之后的攻击力不受 𝑚 的限制)。为了节省体力,他希望通过选择合适的初始攻击力使得他的攻击能让 drd受到最大的伤害,请你帮他计算一下,他的一次攻击最多能使 drd 受到多少伤害。
思路
我们知道,在计算机里数字按二进制存储,也就是一个数的每一位不是0就是1,当0、1进行相同次序的位运算以后得出来的也是0、1。
m<=10^9,即m的位数不超过30位。
我们需要最后进行位运算以后的答案最大,也就是说,从最高位开始到最低位,我们要让每一位尽可能为1。
例如,我们有3位,从第三位开始,我们让第三位为1,即100,值为4,如果第三位为0,值为0;
第二位为1,得到110,值为6,010值为2,000值为0;
总结一下就是,当一个数的第i位经过一系列位运算为1时,对答案的贡献就是1<<i;
当一个数的第i位经过一系列位运算为0时,对答案没有贡献。
那么,我们考虑当一个数的第i位经过一系列位运算为1时的情况:
情况1.第i位数原来是0,经过一系列位运算变成1;
情况2.第i位数原来是1,经过一系列位运算变成1;
对于情况1:如果第i位原来是0,后来变成了1,0~m的二进制中,可以任意实现第i位是0,所以答案直接计算加上贡献值1<<i;
对于情况2:第i位数原来是1,经过一系列位运算变成1,然而,对于这种情况,必须是i小于m是1的最高位,因为大于m是1的最高位就超出了m的范围;
例如5,转换为二进制是101,那么i<=3;
转换一下,也就是说,这个条件是:(1>>i)的值小于m;
这里要注意,计算完以后要让m的这一位变成0,即101,变成001,不然当i=2时,也小于m=5,判断错误。
那么我们只需要对30位全是0,和30位全是1,即a0=0,二进制为000000…,a1=-1,二进制为11111…,来进行一系列的位运算。
然后根据位运算后是1的情况来进行对最后答案的计算。
————————————————
版权声明:本文为CSDN博主「jigsaw_zyx」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jigsaw_zyx/article/details/119120658
代码
#include<iostream>
using namespace std;
pair<string,int> a[100005];
int n,m;
int giao(int bit ,int now)
{
for(int i=1;i<=n;i++)
{
int x=a[i].second>>bit&1;
if(a[i].first=="AND")
now &=x;
else if(a[i].first=="OR")
now |=x;
else
now^=x;
}
return now;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
char str[5];
int x;
scanf("%s%d",str,&x);
a[i]=make_pair(str,x);
}
int val=0,ans=0;
for(int bit=29;bit>=0;bit--)
{
int res0=giao(bit,0);
int res1=giao(bit,1);
if(val+(1<<bit)<=m&&res0<res1)
val+=1<<bit,ans+=res1<<bit;
else
ans+=res0<<bit;
}
cout<<ans<<endl;
}