位运算常用运算
1、左移操作 <<
左移操作可以将二进制数a的每个数位均进行左移,并在移动后右边空出来的数位补0。
例如:a << b意为将二进制数a左移b个数位,在右边空出数位补0。假设a=101,b=1,则将二进制数a左移1位,右边空出来的数位补0,所以新数为1010,同理,a=101,b=2时的新数为10100,依次类推。
需要注意的是,二进制数左移n位等于对应的十进制数 * 2n。例如二进制数101对应的十进制数是5,则将101左移2位后得到的二进制数10100对应的十进制数为5*2 2=20。
2、右移操作 >>
与左移操作类似,右移操作可以将二进制数a的每个数位均进行右移,忽略移动后的小数数位。
例如:a >> b意为将二进制数a右移b个数位,将小数部分(移动前的后b位)删去。假设a=10101,b=2,则移动后的新数为101。
同上,二进制数右移n为等于对应的十进制数/2^n(下取整)。
3、按位与操作 &
按位与操作会将两个二进制数的数位对齐(数位少的高位补0),之后对每一位依次进行与操作。
例如:a=111(补0后为00111),b=11110,则a&b的结果为00110。
&运算可以用来取一个数对应的二进制数的最末位,例如a&1即为a对应二进制数的最末位。二进制数最末位为0则该数为偶数,为1则为奇数。
4、按位或操作 |
与按位与操作相同,按位或操作会将两个二进制数的数位对齐,之后对每一位依次进行或操作。
|运算常用作对某数对应的二进制数的某一位无条件赋值,例如a|1即将a对应二进制数的最末位赋值为1。
5、按位非操作 ~
按位非操作可以将二进制数的每一位进行非(取反)操作。
如果该数为无符号整数类,该操作会将数字后面所有的0均变为1,如果该数为有符号整数类,那么计算机会按照补码的法则对得到的反码继续进行运算
6、按位异或操作 ^
按位异或操作会将两个二进制数的数位对齐,之后对每一位进行如下规则的操作:
如果两数该数位上的数相同(同为0或1),则得到的新数的该数位为0,否则新数该数位为1。
例如:a=00101,b=11100,则a^b的结果为11001。
按位异或操作的逆运算是它本身,也就是说ab=c,则cb=a。
由于某数的一个数位0的结果不变,1的结果取反,在程序中,位运算常用来对一个数对应的二进制数的某一位进行取反,例如a1即将a的最末位进行取反,a10即将a的倒数第二位进行取反。
位运算实用杀招
若当前二进制位为S,对S有下列操作。
①判断第i位是否为0:(S&(1<<i)==0,意思是将1左移i位与S进行与运算后,看结果是否为0
②将第i位设置为1:S|(1<<i),意思是将1左移i位与S进行或运算。
③将第i位设置为0:S&~(1<<i),意思是S与第i位为0,其余位为1的数进行与运算。
例如:S=1010101,i=5。注意二进制位从0开始计数,所以i=5实际上是第6位
S&(1<<i):1010101&0100000=000000
常用操作
1.快速求2^n
1<<n == pow(2,n)
原理:1<<n的意思是1的二进制向左移动n位,则此数二进制形式变成了 100000...000(n个0),恰好是2^n
2.判断奇数偶数
n&1 == 1则为奇数
n&1 == 0则为偶数
原理:n&1的意思是n与1,那么n与1中,1除了右端位为1其他位都是0,则由与运算得到的结果中其他位必定都是0 。
所以最后得到的结果只与1的右端位和n的右端位有关,我们知道1的右端位为1,那么n的右端位只有为1的时候与1进行与运算的结果是1;n的右端位只有为0的时候与1进行与运算的结果是0 。
显然二进制右端位为1的时候该数为奇数,为0时该数为偶数,所以得证。
3.lowbit
a&(-a) 代表着a的二进制的最后一位。
原理:涉及到二进制的补码知识,感兴趣的人可以自己了解。
三、高阶操作
1.a >> b & 1 代表着如果a的第b位为1则为真
用来判断二进制的某一位
原理:a左移b位,则a的右端位就是原来a的第b位,这时与1做与运算(1左边的0由与运算性质得没有影响)就可以得知这一位是1还是0(1&1 == 1,0|1 == 0 )
2.a|(1<<n) 代表着将a的二进制的第n位设为1
原理:1<<n可以看作由一个1和n个0组成的二进制数,其中0的部分由或的性质(0|00,1|01)可以知道不会对二进制位产生影响。
而1的部分由或的性质(1|1==1,0|1=1)可以得出一定是1。
例题解析
一个比较简单的思路,对数组排序,然后逐个统计每个数字出现的次数,复杂度O(nlogn) 。
位运算异或^: 根据 XOR运算的性质,a ^ a=0 。如果某个数出现了两次,那么他们 异或在一起的值恰好为0。
进一步扩展,出现偶数次的数异或和也一定为0,出现奇数次的数异或和一定是这个数本身。因此只要将所有数异或 在一起,剩下的那个数就是出现奇数次的数。
#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
int x;
while (~scanf("%d", &n))
{
int ans = 0;
for (int i = 0; i < n; i++)
{
scanf("%d", &x);
ans ^= x;
}
printf("%d\n", ans);
}
return 0;
}
[oi-wiki](https://oi-wiki.org/math/bit/ "oi-wiki")
标签:运算,二进制,异或,按位,操作,随笔,数位
From: https://www.cnblogs.com/onginer/p/17008944.html