位运算应用与技巧

位运算技巧 总结 - 知乎 (zhihu.com)

位运算简介及实用技巧(一):基础篇 | Matrix67: The Aha Moments

位运算:你必须掌握的几个小技巧_如何精通位运算_香农派我最爱的博客-CSDN博客

下面列举了一些常见的二进制位的变换操作。

功能 | 示例 | 位运算
去掉最后一位 | (101101->10110) |               x>> 1
在最后加一个0 | (101101->1011010) |         x<< 1
在最后加一个1 | (101101->1011011) |         x<< 1+1
把最后一位变成1 | (101100->101101) |         x| 1
把最后一位变成0 | (101101->101100) |         x| 1-1
最后一位取反 | (101101->101100) |                 x^ 1
把右数第k位变成1 |(101001->101101,k=3) |         x | (1<< (k-1))
把右数第k位变成0 |(101101->101001,k=3) |         x & ~(1 << (k-1))
右数第k位取反 |(101001->101101,k=3) |         x ^ (1<< (k-1))
取末k位 |(1101101->1101,k=5) |         x &((1 << k)-1)
取右数第k位 |(1101101->1,k=4) |         x >>(k-1) & 1
把末k位变成1 |(101001->101111,k=4) |         x | ((1<< k)-1)
末k位取反 |(101001->100110,k=4) |                 x ^ ((1<< k)-1)
把右边连续的1变成0 |(100101111->100100000) |         x &(x+1)
把右起第一个0变成1 |(100101111->100111111) |         x | (x+1)
把右边连续的0变成1 |(11011000->11011111) |         x | (x-1)
取右边连续的1 | (100101111->1111) |                        (x ^ (x+1)) >> 1
去掉右起第一个1的左边 | (100101000->1000) |         x & (x ^ (x-1))
最后一个在树状数组中会用到。

/*1、交换两个整数的值:
int a, b;
a = a ^ b;
b = a ^ b;
a = a ^ b;
与下面的等价,不过利用的是^的重要性质,效率当然比算术运算高
a = a + b;
b = a - b;
a = a - b;
2、与2的x次方的运算
int a;
a <<= x;//乘2^x
a >= x;//除2^x
a & (1 << x) - 1 //取a%(2^x)的余数
a & 1//判断奇偶性,为0则a为偶数,否则为奇数
a & (a-1)//判断a是否为2的幂或者0,结果为0代表是,否则代表不是
3、其他常用技巧
int a, b;
a = ~a + 1//取相反数
a = (a ^ (a >> 31)) - (a >> 31) //取绝对值
(a ^ b) > 0 //判断a、b符号是否相同,如果结果>0则相同,否则不同
a + b   = (a ^ b) + ((a & b) << 1)
(a+b)/2 = (a ^ b)/2 + ((a & b) << 1)/2 = (a & b) + ((a ^ b) >> 1) //取平均值
*/

(1)、位运算优先级较低,如果结合其他的运算符,那么最好在使用时加上括号,当然如果很清楚优先级就另当别论了。
(2)、位运算虽说高效,但是很多枚举子集的技巧数据量大点就无法使用了,所以还是得慎用,根据题目的数据范围而定吧。
(3)、使用位运算注意细节的处理,比如说枚举子集时的起点,终点等等。
(4)、使用位运算关键是理解每一个运算的特点,灵活运用它们的性质,并且找到问题与位之间的联系,其实上面的几个枚举集合的技巧都是根据位之间的联系然后运用相应的运算符得出的,一些位运算符也有一些非常重要的特点,比如说异或运算具有交换律,结合律,自反性等等。
(5)、位运算应用很广,体现在很多算法和数据结构上,比如说状态压缩,树状数组等等,在状态压缩中的使用通常是最常见的,很多算法都设计到状态之间的转移,比如说搜索,dp等等。有时候很难表示当前的这个状态,但是通过二进制位便可以解决了,所以位运算还是很方便和实用的,比如说一些在棋盘,网格中要表示某一行/列的状态时的问题。
在数据结构中的应用最常见的是树状数组,借用论文上面的话:树状数组的思想核心在于运用了十进制数与二进制数之间的联系,通过数的二进制形式来决定储存信息,把复杂的问题简单化,方法简单巧妙。
树状数组的优势在于代码长度短,不易出错,思想巧妙,算法复杂度低,维护简单,易推广到二维甚至三维等等。对于数据结构要求操作不复杂的题目,是上佳的选择。
而且线段树也涉及到了简单的右移位运算,或运算等等。
 
————————————————
版权声明:本文为CSDN博主「HopeForBetter」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/consciousman/article/details/52825345

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值