哈理工OJ-2331-Great Atm【二进制思维】

哈理工OJ-2331-Great Atm

题意:
有m+1个数,分别是0~m,从中选取一个数进行n轮(&,|,^)操作后使得最后的结果最大,并输出这个结果

补一个二进制运算【学习一下】
1.按位与运算符(&)
参加运算的两个对象,按二进制位进行“与”运算
运算规则:
0 & 0 = 0;0 & 1 = 0;1 & 0 = 0;1 & 1 = 1;
例如:
3 & 5
0011 & 0101 = 0001
因此 3 & 5 = 1

2.按位或运算符(|)
参加运算的两个对象,按二进制位进行“或”运算

运算规则:
0 | 0 = 0;0 | 1 = 1;1 | 0 = 1;1 | 1 = 1;
例如:
3 | 5
0011 & 0101 = 0111
因此 3 | 5 = 7

3.按位异或运算符(^)
参加运算的两个对象,按二进制位进行“异或”运算

运算规则:
0 ^ 0 = 0;0 ^ 1 = 1;1 ^ 0 = 1;1 ^ 1 = 0;
例如:
3 ^ 5
0011 ^ 0101 = 0110
因此 3 ^ 5 = 6

4.取反运算符(~)
参加运算的两个对象,按二进制位进行“取反”运算

运算规则:
~1 = 0; ~0 = 1;
即:对一个二进制数按位取反,即将0变1,1变0
例如:
~9
即1001 变成 0110

5.左移运算符(<<)
将一个运算符对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
例如:a = a << 2 将 a 的二进制位左移2位,右边补0,
左移1位后a = a * 2;
若左移时舍弃的高位不包含1,则每左移以为,相当于 该数乘以2

6.右移运算符(>>)
将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃.
操作数每右移一位,相当于该数除以2.
例如:a = a >> 2 将a的二进制位右移2位,
左补0 或 补1 即被移数是正还是负。

二进制32位 第32位是运算符号,总共31位数字

思路:
可以先求出二进制的每一位都为0进行n轮操作所得的结果和二进制的每一位都为1进行n轮操作所得的结果,并且分别记录下出所得结果的二进制上每一位的数。
最后遍历二进制的31位,如果原先这一位为0,但操作后的结果中这一位为1,那么最后的答案肯定要加上这一位(≤m的数中这一位肯定可以为0);
如果原先这一位为1,操作后的结果中这一位也为1,此时我们要先判断这一位的十进制是否大于m,如果不大于那么最后答案也要加上这一位(因为≤m的数中这一位可以为1),最后加得的答案就是最终的结果了
加重的重点!!
看了半天才懂题意,没有思路
感谢:http://blog.csdn.net/blesslzh0108/article/details/68957626

#include<stdio.h>

int temp[40][2];

int main()
{
    int n,m,x;
    char s[10];
    while(~scanf("%d%d",&n,&m))
    {
        int Max=2147483647,Min=0;//
        for(int i=0; i<n; ++i)
        {
            scanf("%s %d",s,&x);
            if(s[0]=='A')
                Max&=x,Min&=x;
            else if(s[0]=='O')
                Max|=x,Min|=x;
            else if(s[0]=='X')
                Max^=x,Min^=x;
        }
        for(int i=30; i>=0; --i)//记录二进制的每一位为0或为1时所得的(二进制中这一位的)结果
        {
            temp[i][0]=(Min&(1<<i));
            temp[i][1]=(Max&(1<<i));
        }
        int ans=0;
        for(int i=30; ~i; --i)
        {
            if(temp[i][0])
                ans=ans|(1<<i);
            else if(temp[i][1])
            {
                if((1<<i)<=m)
                {
                    ans=ans|(1<<i);
                    m-=(1<<i);
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值