关于一些位运算的小记
位运算符
对于位运算完全不熟悉,因此开个小记来陆续记录一些遇到的常用位运算
```&```:按位与,对应的二进制位均为1时返回1,否则返回0;
```|```:按位或,对应的二进制位有一个为1时返回1,否则返回0;
```^```:按位异或,对应的二进制位不同时返回1,否则返回0;
```~```:按位非,对每一位取反;
```<<```:左移;
```>>```:右移;
##位运算的一些技巧
###```i<>j```
前者表示i的二进制表示左移j位,等效于i/(2^j);后者表示i的二进制表示右移j位,等效于i*(2^j);
###i&1
求i的最后一位,可判断奇数偶数;
###i^j
比较i与j的每一位,不同时返回1,否则返回0;因此i==j时,i^j=0;
###i&(-i)
返回 i 的二进制数表示为1的最低位的权值,如1001则返回1,1100则返回4,1110则返回2;该运算常用于求和或更新树状数组
###i&(i-1)
使i二进制表示下最右边的1变为0;
因此:
①可以用i&(i-1)的结果是否为0来判断i是否是2的幂;
②如果要比较m,n的二进制表示有多少位不同,可以
```C++
int n,m,t,cnt=0;
cin >> n>>m;
t = n ^ m;
while (t)
{
cnt++;
t &= (t - 1);
}
cout << cnt;
```
n^m的结果将n与m的不同位变为1,相同位变为0,因此只需统计t有多少个1;
用t&(t-1)来依次将t最右边的1改为0,直到t为0;操作的次数即为1的个数。
由此统计m,n不同位的个数
###i+((i+1)&(-(i+1)))
i+1将i最低位的0变为1,后面的1变为0,再用(i+1)&-(i+1)取得其最低位1的权值,加到i上,得到的效果就是将i最低位的0变成1
###异或运算的一些性质
异或运算的逆运算也是异或运算,即:a^b=c,则有a=b^c;
异或运算具有结合律,因此a^b^b=a