位运算
位运算简介
数据在计算机内存中都是以二进制的形式储存的,位运算就是直接对整数在内存的二进制进行运算操作。(参与位运算的数只限整数)所以相对于其他部分运算符,他们的运算速度、更快节省时间,对于一些该死的卡时间的题目位运算可以缩短运算时间,万一就哇(WA)了呢在算法复杂度已经难以优化的时候可以试试。
数值补码表示方法
数值在计算机内存中以补码形式存储;
正数补码:与原码相同;
负数补码:符号位不变,其他按照原码取反,最后加1。
无符号整型
C++ unsigned short的范围是065535,有符号的情况下其范围是-3276832767当作无符号处理的时候,他们补码最高位的1不在表示负号,而是变成有效数字位。
位运算符
按位与 & 全一则一,否则为零
按位或 | 有一则一,否则为零
按位取反 ~ 是零则一,是一则零
按位异或 ^ 不同则一,相同则零
左位移 << a<<k等价于a*2^k
右位移 >> a>>k等价于a/2^k
按位与运算 &
格式:x&y,x and y
应用:
(x&1)==0/1;//判断整数奇偶性
x&((1<<n)-1);//取出整数x的低n位
x& -x;//取出x最右边的1
(x&(x-1))==0;//判断一个数是否是2的n次幂
while(x){
cnt++;
x=x&(x-1);
}//判断一个二进制表示的数中1的个数
按位或运算 |
x | 1;//最后一位变成1
x | ((1<<n)-1);//用于特定位上无条件赋值(低n位置1)
x | (x+1);//用于特定位上的无条件复制(右起第一个0置1)
x | (x-1);//用于特定位上的无条件复制(最右连续0置1)
按位异或运算 ^
x^1;//最后一位取反
int a,b;
a=a^b,b=a^b,a=a^b;//实现变量互换
因为位运算经常插在各个题目中出现只要你愿意,所以这里就只例举一道题目
P1100 高低位交换
题目传送
题目描述
给出一个小于2^32的正整数。这个数可以用一个3232位的二进制数表示(不足3232位用00补足)。我们称这个二进制数的前1616位为“高位”,后1616位为“低位”。将它的高低位交换,我们可以得到一个新的数。试问这个新的数是多少(用十进制表示)。
例如,数1314520用二进制表示为0000 0000 0001 0100 0000 1110 1101 1000(添加了1111个前导00补足为3232位),其中前16位为高位,即0000 0000 0001 0100;后16位为低位,即0000 1110 1101 1000。将它的高低位进行交换,我们得到了一个新的二进制数0000 1110 1101 1000 0000 0000 0001 0100。它即是十进制的249036820。
输入格式
一个小于2^32的正整数
输出格式
将新的数输出
输入
1314520
输出
249036820
CODE
#include <bits/stdc++.h>
using namespace std;
int main()
{
unsigned long long num;//注意在用printf的时候unsigned无符号类型需要用%u输入输出,使用输入输出流的话就不需要在意这些,不然32位会卡数据
scanf("%u", &num);
printf("%u\n", (num << 16) | (num >> 16));//将num左右位移16位(不够自动补0),取或
return 0;
}