【Bzoj3668】起床困难综合症

5 篇文章 0 订阅
1 篇文章 0 订阅

题意

给你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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值