题意
给你n个操作包括按位与,按位或,按位异或。还有一个参数m,请你找0~m中的经过n个操作后最大的数,输出这个最大值。
分析
首先二进制运算的每一位是相对独立的,可以考虑它的每一位。首先,如果某位经过n次操作能变成1,这一位就要选(如果能选0就选0,使数字尽量小)。如果无论1,0都无法变成1,也选0。(在这一位上填1产生的贡献比在它后面全填上1还要大。能填则填。)
#include <cstdio>
#include <algorithm>
#define Rep( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i<=(i##_END);i++)
#define For( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i++)
#define Lop( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i>=(i##_END);i--)
#define Dnt( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i--)
using std :: max;
using std :: min;
const int maxx = 100000 + 25;
int opt[maxx],a[maxx];
int ans,n,m,x,y,z;
char s[10];
int calc(int x){
Rep( i , 1 , n ){
if(opt[i] == 1) x &= a[i];
if(opt[i] == 2) x |= a[i];
if(opt[i] == 3) x ^= a[i];
}
return x;
}
int main(){
scanf("%d%d",&n,&m);
Rep( i , 1 , n ){
scanf("%s%d",s,&a[i]);
if(s[0] == 'A') opt[i] = 1;
if(s[0] == 'O') opt[i] = 2;
if(s[0] == 'X') opt[i] = 3;
}
Lop( i , 31 , 0 ){
int mi = (1<<i);
if(ans + mi > m) continue;
int ans1 = calc(ans+mi) & mi;
int ans2 = calc(ans) & mi;
ans = ans1 > ans2? ans+mi : ans;
}
printf("%d\n",calc(ans));
return 0;
}