当前位置: 代码迷 >> 综合 >> 0x01——位运算
  详细解决方案

0x01——位运算

热度:33   发布时间:2023-12-05 18:28:51.0

基础知识及二进制常见用法

  • 前言

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

例题:

  1. a^b
  2. 64位整数乘法
  • 二进制状态压缩

二 进 制 状 态 压 缩 , 是 指 将 一 个 长 度 为 m 的 b o o l 数 组 用 一 个 m 位 的 二 进 制 整 数 表 示 {\color{Red} 二进制状态压缩,是指将一个长度为m的bool数组用一个m位的二进制整数表示} mboolm
并 储 存 的 方 法 。 利 用 下 列 位 运 算 操 作 可 以 实 现 原 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))

例题:

  1. 最短Hamilton路径
    2.起床困难综合症
  • 位的其他应用
  1. 成对变换

通过计算可以发现,对于非负整数 n : n: n:

  • 当 n 为 偶 数 时 , n x o r 1 等 于 n + 1 当n为偶数时,n~xor~1等于n + 1 nn xor 1n+1
  • 当 n 为 奇 数 时 , n x o r 1 等 于 n ? 1 当n为奇数时,n~xor~1等于n - 1 nn xor 1n?1

因 此 , “ 0 与 1 ” , “ 2 与 3 ” , “ 4 与 5 ” . . . 关 于 x o r 1 运 算 构 成 “ 成 对 变 换 ” 因此,“0与1”,“2与3”,“4与5”...关于xor1运算构成“成对变换” 012345...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节)给出。

  1. lowbit运算

    lowbit运算定义非负整数 n ~n~  n 在二进制表示下 “ 最 低 位 的 1 及 其 后 边 所 有 的 0 ” “最低位的1及其后边所有的0~” 10  构成的数值。例如 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  10 ~ k ? 1 位 都 是 0 。 k - 1 位 都 是 0。 k?10
    为 了 实 现 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?10
    而 且 n 的 第 k + 1 到 最 高 位 恰 好 与 原 来 相 反 , 所 以 而且n的第~k+1~到最高位恰好与原来相反,所以 n k+1 
    n & ( n\&( n&(~ n + 1 ) 仅 有 第 k 位 为 1 , n+1)仅有第k位为1, n+1)k1
    其 余 位 都 是 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节)中的一个基本运算。