& 与 两者都为1则为1,有一个不为1则为0
| 或 有一个为1则为1,都为0则为0
! 非 取反 0对应1,false对应true (逻辑取反)
~ 非 按位取反,0变为1,1变为0
^ 异或 两者相同为0,不同为1
~x+1表示一个数的补码
-n=~n+1
移位运算
左移 << 在二进制表示形式下把数字同时向左移动,低位以0填充,高位越界后舍弃
算术右移 在二进制补码表示下把数字同时向右移动,高位以符号位填充,低位越界后舍弃
二进制状态压缩
/*
取出整数 n 在二进制表示下的第 k 位 (n >> k) & 1
取出整数 n 在二进制表示下的第 0 ~ k-1 位(后k位) n & ((1 << k) - 1)
把整数 n 在而今汉字表示下的第 k 位取反 n ^ (1 << k)
对整数 n 在二进制表示下的第 k 位赋值1 n | (1 << k)
对整数 n 在二进制表示下的第 k 位赋值0 n & (~ (1 << k))
*/
成对变换
当 n 为 偶数时 n^1 等于n+1
当 n 为 奇数时 n^1 等于n-1
因此,“0与1”“2与3”“4与5”。。。。关于x^1运算构成“成对变换”
这个性质经常用于图论邻接表中边集的存储,
lowbit运算
lowbit(n)定义为非负整数 n 在二进制表示下“最低位的1及其后边所有的0”构成的数值
设 n>0 ,n的第k位为1,第 0~k-1 位都是0
先把n取反,此时第k位为0,第 0~k-1 位都是1,再令n=n+1 此时因为进位,第k位变为1,第 0~k-1 位都是0
在上面的取反加一操作后,n的第k+1到最高位恰好与原来相反,所以n&(~n+1)仅有第k位为1,其余位都是0,而在补码表示下~n+1=-n
所以: lowbit(n)=n&(~n+1)=n&-nzhao
lowbi运算配合Hash可以找出整数二进制表示下所有是1的位,所花费的时间与1的个数同级
两种方法
#include<iostream>
using namespace std;
int H[37];
int main(){
for(int i = 0; i < 36; i++) H[(1ll << i)%37] = i;
int n;
while(cin >> n){
while(n >0){
cout << H[(n & -n)% 37] <<" ";
n -= n & -n;
}
cout << endl;
}
}
#include <iostream>
using namespace std;
const int MAX_N =1<<20;
int H[MAX_N + 1];
int main(){
int n;
for(int i = 0; i <= 20; i++) H[ 1 << i] = i;
while(cin>>n){
while(n > 0){
cout<<H[n&-n]<<" ";
n -= n & -n;
}
cout<<endl;
}
}