题解 | #起床困难综合症#
起床困难综合症
https://ac.nowcoder.com/acm/problem/17857
思路
按位确定以下,在某一位如果是0,那么经过这些操作之后是0还是1,类似,如果某一位是1的时候也可以这样确定。 那么我们就可以用logn的时间算出某一个数经过这些操作之后的值,但是这里m有点大,我们不能直接枚举。 我们从高位向低位考虑,如果这一位上放0可以变成1,就直接放0,否则看放1是否能变成1并且不会超过m的范围, 这样处理最后就能得到每一位是0还是1啦。
代码
//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;
//int read(){ int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,m,res;
bool num0[65],num1[65];
string op;
void Solve(){
cin>>n>>m;
bitset<40>num0,num1;
num1.set();
for(int i=1,x;i<=n;i++){
cin>>op>>x;
if(op=="AND"){
for(int j=0;j<=62;j++){
num0[j]=num0[j]&((x>>j)&1ll);
num1[j]=num1[j]&((x>>j)&1ll);
}
}else if(op=="OR"){
for(int j=0;j<=62;j++){
num0[j]=num0[j]|((x>>j)&1ll);
num1[j]=num1[j]|((x>>j)&1ll);
}
}else if(op=="XOR"){
for(int j=0;j<=62;j++){
num0[j]=num0[j]^((x>>j)&1ll);
num1[j]=num1[j]^((x>>j)&1ll);
}
}
}
// for(int i=0;i<=4;i++) cout<<i<<" "<<num0[i]<<" "<<num1[i]<<"!!\n";
int ans=0,now=0;
for(int i=62;i>=0;i--){
if(num0[i]||num1[i]){
if(num0[i]) ans+=(1ll<<i);
else if(now+(1ll<<i)<=m) now+=(1ll<<i),ans+=(1ll<<i);
}
}
cout<<ans<<"\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("in.cpp","r",stdin);
// freopen("out.cpp","w",stdout);
int T=1;
//cin>>T;
while(T--){
Solve();
}
// cerr<<clock()*1.0/CLOCKS_PER_SEC<<endl;
return 0;
}