【洛谷P2114】起床困难综合征 位运算+贪心

题目大意:给定 N 个操作,每个操作为按位与、或、异或一个固定的数字,现在要求从 0 到 M 中任选一个数字,使得依次经过 N 个操作后的值最大。

题解:位运算有一个重要的性质是:位运算时,无进位产生,每一位之间相互独立。因此,可以从高到低依次考虑每一位对答案的贡献值,计算每一位经过这 N 个操作后的值,比较后更新答案贡献即可。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;

int n,m;
pair<string,int> a[maxn];

void read_and_parse(){
    char s[5];int val;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s%d",s,&val);
        a[i]=make_pair(s,val);
    }
}

int calc(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;
}

void solve(){
    int val=0,ans=0;
    for(int i=29;i>=0;i--){
        int res0=calc(i,0);
        int res1=calc(i,1);
        if(val+(1<<i)<=m&&res1>res0)ans|=res1<<i,val|=1<<i;
        else ans|=res0<<i;
    }
    printf("%d\n",ans);
}

int main(){
    read_and_parse();
    solve();
    return 0;
}
posted @ 2019-01-13 15:15  shellpicker  阅读(156)  评论(0编辑  收藏  举报