P2114 [NOI2014] 起床困难综合症(贪心+位运算)

链接

题目大意:

要求在0--m之间的数,经过n次位运算后,最大是多少?

题解:

位运算的特点是,每一位是独立的,不存在进位和借位。

假设x∈[0,m],经过位运算后得到的结果最大,为z
位运算的特点 各个位互不影响
先用各位都为0和各位都为1的数经过所有的位运算
接下来我们来构造出x
对于 1000 > 0111,所以我们使z的高位尽可能有1
经过位运算出现1的情况有
(1)当该位为0,经过一系列位运算变为1,最优
(2)当该位为1,经过一系列位运算变为1,
当将该位变为1时,仍小于m,则将该位变为1.
m<=10^9<2^30

代码

#include<bits/stdc++.h>
using namespace std;

int n,m;
int a0,a1;
long long ans;

int main()
{
    cin>>n>>m;
    a0=0;a1=(1<<30)-1;
    for(int i=1;i<=n;i++)
    {
        string s;
        int x;
        cin>>s>>x;
        if(s[0]=='X') a0^=x,a1^=x;
        if(s[0]=='A') a0&=x,a1&=x;
        if(s[0]=='O') a0|=x,a1|=x;
    } 
    for(int i=29;i>=0;i--)
    {
        if(a0&(1<<i)) ans|=(1<<i);
        else if((a1&(1<<i))&&(m>=(1<<i)))
        {
            ans|=(1<<i);
            m=m-(1<<i);
        }
    }
    cout<<ans;
    return 0;
}

 

posted @ 2021-04-20 20:45  ANhour  阅读(58)  评论(0编辑  收藏  举报