C语言 | Pascal语言 |
---|---|
a & b | a and b |
a l b | a or b |
a ^ b | a xor b |
~a | not a |
a << b | a shl b |
a >> b | a shr b |
0x | $ |
because using chinese will endl automatically, I will try my best to type in English;
The blog is referred from matrix67,a NOI gold winner,a man who lead me into programming competition from very begining;
Since he gave the example in PASCAL I give the table above first;
But I will translate them int c++;
I list some experience below;
功能 | 示例 | 位运算 |
---|---|---|
去掉最后一位 | (101101->10110) | x shr 1 |
在最后加一个0 | (101101->1011010) | x shl 1 |
在最后加一个1 | (101101->1011011) | x shl 1+1 |
把最后一位变成1 | (101100->101101) | x or 1 |
把最后一位变成0 | (101101->101100) | x or 1-1 |
最后一位取反 | (101101->101100) | x xor 1 |
把右数第k位变成1 | (101001->101101,k=3) | x or (1 shl (k-1)) |
把右数第k位变成0 | (101101->101001,k=3) | x and not (1 shl (k-1)) |
右数第k位取反 | (101001->101101,k=3) | x xor (1 shl (k-1)) |
取末三位 | (1101101->101) | x and 7 |
取末k位 | (1101101->1101,k=5) | x and (1 shl k-1) |
取右数第k位 | (1101101->1,k=4) | x shr (k-1) and 1 |
把末k位变成1 | (101001->101111,k=4) | x or (1 shl k-1) |
末k位取反 | (101001->100110,k=4) | x xor (1 shl k-1) |
把右边连续的1变成0 | (100101111->100100000) | x and (x+1) |
把右起第一个0变成1 | (100101111->100111111) | x or (x+1) |
把右边连续的0变成1 | (11011000->11011111) | x or (x-1) |
取右边连续的1 | (100101111->1111) | (x xor (x+1)) shr 1 |
去掉右起第一个1的左边 | (100101000->1000) | x and (x xor (x-1)) |
eg.1 计算一个32位整数的二进制中1的个数的奇偶性,奇1偶0
int x;
{
cin>>x;
x^= (x >> 1);
x^= (x >> 2);
x^= (x >> 4);
x^= (x >> 8);
x^= (x >> 16);
cout <<x&1;
}
^lead to 奇1偶0
After the first line,every bit from the new x stand for the two bit from the former x .
So the second line >>x two bit to skip one useless bit;
And So do lines next.
eg2.计算二进制中的1的个数
x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
0x55 is 01010101,0x33is00110011,etc;
every line makes two bit between sum up
eg3求32位整数的前导0个数
int nlz(unsigned x)
{
int n;
if (x == 0) return(32);
n = 1;
if ((x >> 16) == 0) {n = n +16; x = x <<16;}
if ((x >> 24) == 0) {n = n + 8; x = x << 8;}
if ((x >> 28) == 0) {n = n + 4; x = x << 4;}
if ((x >> 30) == 0) {n = n + 2; x = x << 2;}
n = n - (x >> 31);
return n;
}
二分法
eg4.我们称这个二进制数的前16位为“高位”,后16位为“低位”。将它的高低位交换
int n;
cin>>n;
cou<<(n >> 16) | (n <<16) ;
eg5. 06年NOIp模拟赛(一) by Matrix67 第四题
eg6.n皇后问题位运算版