题意:玩家的初始攻击力范围[0,m],求一个合理的初始攻击力获得的最大伤害值
分析:位运算的一个特点是二进制下不进位,x0可以任意选择的情况下,ans的第几位是1/0仅与x0的第几位是1/0有关,和其他的无关,所以我们可以依次枚举每一位是0和1的情况哪个比较好来进行选择
限制条件:
- 初始值的范围必须在[0,m]内
- 贪心的想,为了初始值范围在范围内,1,0结果都为1时,优先选择0
由于要求最大的伤害值,因为位运算不会进位,并且门的类型对答案也会有贡献,所以即使m很小,我们也要从2^29开始枚举,(≈1e9),只不过是直接让该位=0
从高位枚举:
从高位枚举的原因是,保证初始值不会超过m的范围,并且 答案 选择高位的1一定是更好的,如果从低位开始枚举,高位原本可以选择1结果选择0,这个肯定不是最优答案
同时,只有某位上取1才对val有共享,取0的时候只要更新res就可以了
#include <iostream>
#include <algorithm>
using namespace std;
const int N=100005;
typedef pair<string,int> PII;
PII a[N];
int n,m;
int cal(int bit,int x)
{
for(int i=0;i<n;i++)
{
string op=a[i].first;
int v=a[i].second>>bit&1;
//v表示t该位上的元素
if(op=="XOR") x^=v;
if(op=="OR") x|=v;
if(op=="AND") x&=v;
}
return x;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>a[i].first>>a[i].second;
int val=0,res=0;
for(int bit=29;bit>=0;bit--)
{
int res0=cal(bit,0);
int res1=cal(bit,1);
//比较1,0哪个更好,相等的情况下优先选择0
if(res0<res1&&val+(1<<bit)<=m)
{
res+=res1<<bit;
val+=1<<bit;
}
else res+=res0<<bit;
}
cout<<res;
return 0;
}