学习目标
1. 理解与掌握 C++ 中的位运算。
2. 灵活应用位运算优化程序。
任何信息在计算机中都是采用二进制表示的,数据在计算机中是以补码形式存储的,位运算就是直接对整数在内存中的二进制位进行运算。由于位运算直接对内存数据进行操作,不需要转换成十进制,因此处理速度非常快,在信息学竞赛中往往可以优化理论时间复杂度的系数。同时,一个整数的各个二进制位互不影响,利用位运算的一些技巧可以帮助我们简化程序代码。
一、位运算符
C++ 提供了按位与(&)、按位或(| )、按位异或(^)、取反(~)、左移(<<)、右移(>>)这 6 种位运算符。 这些运算符只能用于整型操作数,即只能用于带符号或无符号的 char、short、int 与 long 类型。
(1)按位与运算符(&)
“a&b”是指将参加运算的两个整数a和b,按二进制位进行“与”运算。
参加运算的两个数据,按二进制位进行“与”运算。
运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:两位同时为“1”,结果才为“1”,否则为0
例如:3&5 即 0000 0011& 0000 0101 = 00000001 因此,3&5的值得1。
另,负数按补码形式参加按位与运算。
按位与&比较实用的例子:
1、比如我们经常要用的是否被2整除,一般都写成 if(n % 2 == 0) 可以换成 if((n&1) == 0)
2、按位与运算可以取出一个数中指定位。例如:要取出整数84从左边算起的第3、4、5、7、8位,只要执行84 & 59,因为84对应的二进制为01010100,59对应的二进制为00111011,01010100 & 00111011= 00010000 可知84从左边算起的第3、4、5、7、8位分别是0、1、0、0、0。
3、清零。如果想将一个单元清零,使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
(2)按位或运算符(|)
参加运算的两个对象,按二进制位进行“或”运算。
运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :参加运算的两个对象只要有一个为1,其值为1。
例如:3|5 即 00000011 | 0000 0101 = 00000111 因此,3|5的值得7。
另,负数按补码形式参加按位或运算。
按位或 (|) 比较实用的例子
可以用一个unsigned int 来存储多个布尔值。比如一个文件有读权限,写权限,执行权限。看起来要记录3个布尔值。我们可以用一个unsigned int也可以完成任务。
一个数r来表示读权限,它只更改个位来记录读权限的布尔值
00000001 (表示有读权限)
00000000 (表示没有读权限)
一个数w表示写权限,它只用二进制的倒数第二位来记录布尔值
00000010 (表示有写权限)
00000000 (表示没有写权限)
一个数x表示执行权限,它只用倒数第三位来记录布尔值
00000100 (表示有执行权限)
00000000 (表示没有执行权限)
那么一个文件同时没有3种权限就是
~r | ~ w | ~ x 即为 00000000,就是0
只有读的权限就是
r | ~w | ~x 即为 00000001,就是1
只有写的权限就是
~r | w | ~x 即为 00000010,就是2
一个文件同时有3种权限就是
r | w | x 即为 00000111,就是7
(3)按位异或运算符(^)
参加运算的两个数据,按二进制位进行“异或”运算。
运算规则:0 ^ 0=0; 0 ^ 1=1; 1^ 0=1; 1^1=0;
即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
下面重点说一下按位异或,异或 其实就是不进位加法,如1+1=0,,0+0=0,1+0=1。
异或的几条性质:
1、交换律:a ^ b=b ^ a
2、结合律:(a ^ b) ^ c == a^ (b ^ c)
“异或运算”的特殊作用:
(1)使特定位翻转: 例:X=10101110,使X低4位翻转,用X ^ 0000 1111 = 1010 0001即可得到。
(2)与0相异或,保留原值 ,10101110^ 00000000 = 1010 1110。
(3)对于任何数x都有――自反性:x^ x=0,x^ 0=x 例如:A^B ^ B = A
(4)交换二个数:a =a ^ b; b = b ^ a; a = a ^ b;
按位异或应用举例1:
给出 n 个整数,n 为奇数,其中有且仅有一个数出现了奇数次,其余的数都出现了偶数次。用线性时间复杂度、常数空间复杂度找出出现了奇数次的那个数。
【输入样例】
9
3 3 7 2 4 2 5 5 4
【输出样例】
7
#include<bits/stdc++.h>
using namespace std;
int main()
{
int i,n,m,a;
cin