基础知识及二进制常见用法
- 前言
bit是度量信息的单位,包含0和1两种状态。计算机的各种运算最后无不归结位一个个bit的变化。熟练掌握并利用位运算,能够帮助我们理解程序运行中的种种表现,提高程序循行的时空效率,降低编程复杂度。
- 运算符优先级
从左到右优先级依次降低
加减 移位 比较大小 位与 异或 位或 +,- <<,>> <,>==,!= & xor(C++^) |
- 位与memset
我们都知道,memset可以以字节为单位初始化变量或者数组,这里有几个特>别的数字:
- 0x3F3F3F3F 1061109567
-> 0x7F7F7F7F 2147483647- 0xFFFFFFFF -1
观察这几个数字,我们会发现0x3F3F3F3F是个很有用的数字,原因如下:
- 可以直接用memset初始化
- 0x3F3F3F3F的两倍不会超过int的最大范围
- 这个数足够大
这也是常常使用INF = 0x3F3F3F3F的原因
memset(a,0x3f,sizeof a);
- 移位运算
>> << 即除以2向下取整 1 < < n = 2 n , n < < 1 = 2 ? n 1<<n = 2^{n} , n<<1 = 2 * n 1<<n=2n,n<<1=2?n
例题:
- a^b
- 64位整数乘法
- 二进制状态压缩
二 进 制 状 态 压 缩 , 是 指 将 一 个 长 度 为 m 的 b o o l 数 组 用 一 个 m 位 的 二 进 制 整 数 表 示 {\color{Red} 二进制状态压缩,是指将一个长度为m的bool数组用一个m位的二进制整数表示} 二进制状态压缩,是指将一个长度为m的bool数组用一个m位的二进制整数表示
并 储 存 的 方 法 。 利 用 下 列 位 运 算 操 作 可 以 实 现 原 b o o l 数 组 中 对 应 下 标 的 存 取 。 {\color{Red} 并储存的方法。利用下列位运算操作可以实现原bool数组中对应下标的存取。} 并储存的方法。利用下列位运算操作可以实现原bool数组中对应下标的存取。
操作 运算 取出整数n在二进制表示下的第k位 ( n > > k ) & 1 (n>>k)\&1 (n>>k)&1 取出整数n在二进制表示下的第0~k-1位(后k位) n & ( ( 1 < < k ) ? 1 ) n\&((1<<k)-1) n&((1<<k)?1) 把整数n在二进制表示下的第k位取反 n x o r ( 1 < < k ) n~xor~(1<<k) n xor (1<<k) 对整数n在二进制表示下的第k位赋值1 n n n| ( 1 < < k ) (1<<k) (1<<k) 对整数n在二进制表示下的第k位赋值0 n & ( n\&( n&(~ ( 1 < < k ) ) (1<<k)) (1<<k))
例题:
- 最短Hamilton路径
2.起床困难综合症
- 位的其他应用
- 成对变换
通过计算可以发现,对于非负整数 n : n: n:
- 当 n 为 偶 数 时 , n x o r 1 等 于 n + 1 当n为偶数时,n~xor~1等于n + 1 当n为偶数时,n xor 1等于n+1
- 当 n 为 奇 数 时 , n x o r 1 等 于 n ? 1 当n为奇数时,n~xor~1等于n - 1 当n为奇数时,n xor 1等于n?1
因 此 , “ 0 与 1 ” , “ 2 与 3 ” , “ 4 与 5 ” . . . 关 于 x o r 1 运 算 构 成 “ 成 对 变 换 ” 因此,“0与1”,“2与3”,“4与5”...关于xor1运算构成“成对变换” 因此,“0与1”,“2与3”,“4与5”...关于xor1运算构成“成对变换”
这一性质经常用于图论邻接表的储存。
在具有无向边(双向边)的图中把一对正反方向的边分别储存在邻接表数组的 n n n与 n + 1 n+1 n+1 位置( n ~n~ n 为偶数),就可以通过 x o r 1 ~xor~1~ xor 1 的运算获得与当前边 ( x , y ) ~(x,y)~ (x,y) 反向的边 ( y , x ) ~(y,x)~ (y,x) 的储存位置。详细应用我们将在讲解邻接表时(第0x13节)给出。
-
lowbit运算
lowbit运算定义非负整数 n ~n~ n 在二进制表示下 “ 最 低 位 的 1 及 其 后 边 所 有 的 0 ” “最低位的1及其后边所有的0~” “最低位的1及其后边所有的0 ” 构成的数值。例如 n = 10 的二进制表示为 ( 1010 ) 2 (1010)_{2} (1010)2?,则 l o w b i t ( n ) = 2 = ( 10 ) 2 lowbit(n) = 2 = (10)_{2} lowbit(n)=2=(10)2?。下面我们来推导 l o w b i t ( n ) ~lowbit(n)~ lowbit(n) 的公式。
设 n > 0 , n 的 第 k 位 是 1 , 第 0 设n > 0 ,~n ~的 第 ~k ~位 是 ~1,第0 设n>0, n 的第 k 位是 1,第0 ~ k ? 1 位 都 是 0 。 k - 1 位 都 是 0。 k?1位都是0。
为 了 实 现 l o w b i t 运 算 , 先 把 n 取 反 , 此 时 第 0 为了实现~lowbit~运算,先把~n~取反,此时第0 为了实现 lowbit 运算,先把 n 取反,此时第0
~ k ? 1 位 都 是 1 。 k-1位都是~1~。 k?1位都是 1 。
在 令 n = n + 1 , 此 时 因 为 进 位 , 第 k 位 变 为 1 , 在令n~=~n~+~1,此时因为进位,第~k~位变为1, 在令n = n + 1,此时因为进位,第 k 位变为1,
第 0 第0 第0 ~ k ? 1 位 都 是 0 。 k - 1 位都是0。 k?1位都是0。
而 且 n 的 第 k + 1 到 最 高 位 恰 好 与 原 来 相 反 , 所 以 而且n的第~k+1~到最高位恰好与原来相反,所以 而且n的第 k+1 到最高位恰好与原来相反,所以
n & ( n\&( n&(~ n + 1 ) 仅 有 第 k 位 为 1 , n+1)仅有第k位为1, n+1)仅有第k位为1,
其 余 位 都 是 0 , 而 在 补 码 表 示 下 其余位都是0,而在补码表示下 其余位都是0,而在补码表示下~ n = ? 1 ? n , 因 此 : n~=~-1-n,因此: n = ?1?n,因此:
l o w b i t ( n ) = n & ( lowbit(n) ~=~n\&( lowbit(n) = n&(~ n + 1 ) = n & ( ? n ) n+1)~=~n\&(-n) n+1) = n&(?n)l o w b i t lowbit~ lowbit 操作可以配合Hash(0x14节)可以找到整数二进制表示下所有是1的位。
此外, l o w b i t ~lowbit~ lowbit 运算也是树状数组(0x42节)中的一个基本运算。