p2114 起床困难综合症
分析
orz zwj
最好想到的方法是我们枚举每一位是0还是1,然后暴力求出经过n个操作之后的结果来决定这一位是0还是1
然后我们发现这种暴力的做法居然能a
但是还有更好的方法
我们只考虑开始的数每位都是0和每位都是1这两种情况
然后算出n次操作之后变成了什么
如果由0变1则我们这一位肯定是0
否则如果由1变1我们就将这一位设为1
其它无法变成1的位全部赋为0即可
详见代码
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int n,m;
int opt[100100],sum[100100],is[100100],Ans;
//opt = 1 OR
//opt = 2 XOR
//opt = 3 AND
inline int have(int x,int wh){
if(opt[wh]==1)return x|sum[wh];
else if(opt[wh]==2)return x^sum[wh];
else return x&sum[wh];
}
inline void deal(int x){
int i,j,k=(x==0?0:1);
for(i=1;i<=n;i++)x=have(x,i);
for(i=30;i>=0;i--)
if(x&(1<<i)&&!is[i]&&(m>=(1<<i)||!k)){
Ans+=(1<<i);
is[i]=1;
if(k)m-=(1<<i);
}
return;
}
int main(){
int i,j,k;
scanf("%d%d",&n,&m);
char s[50];
for(i=1;i<=n;i++){
scanf("%s",s);
if(s[0]=='O')opt[i]=1;
else if(s[0]=='X')opt[i]=2;
else opt[i]=3;
scanf("%d",&sum[i]);
}
deal(0);
deal(-1);
printf("%d\n",Ans);
return 0;
}