妙用位运算

目录

妙用位运算

知识简介

应用

补充


妙用位运算

知识简介

bit是度量信息的单位,包含0和1两种状态。

计算机的各种运算最后无不归结为一个个bit的变化。

熟练掌握并利用位运算,能够帮助我们理解程序运行中的种种表现,提高程序运行时的时空效率,降低编程复杂度。

异或左移算术右移
&|!nor<<>>
5&3=15|3=7~5=2,~3=45^3=65<<1=105>>1=2

(此处为了与次幂区别开,本篇中异或均写为nor,但在实际使用中以^为准)

移位运算

左移

在二进制表示下把数字同时向左移动,地位以0填充,高位越界后舍弃。

1 << n = 2^n n << 1 = 2n

算术右移

在二进制补码表示下把数字向右移动,高位以符号位填充,低位越界后舍弃。

算术右移等于除以2向下取整。

  (-3)>>1 = -2     3>>1 =1

此处与整除运算有所区别,”整数/2“实现为 “除以2向0取整”,

      (-3) / 2 = -1       3/2 = 1

补码

  • 无符号数:直接把该32为编码C看作32位二进制数N

  • 有符号数:以最高为为符号位,0为正,1为负

    正数的补码均为它本身,负数的补码为编码C按位取反加1。

  • 注:计算机使用补码进行各种加减乘除运算,补码可以保证每个数值都有唯一的表示方式。(此篇以C++为准,Java中没有无符号数)

应用

快速幂

a^b, 求ab次方对p取模的值,其中1<=a,b,p<=10^9。

根据数学尝试,每一个正整数可以唯一表示为若干指数不重复的2的次幂的和。也就是说如果b在二进制表示下有k为,其中第i(0<=i<k)位的数字是Ci,那么就有:

 于是就有:

因为k=[log2(b+1)]([]为向上取整),所以上式乘积项的数量不多于[log2(b+1)]个。又因为:

所以我们很容易通过k次地推求出每个乘积项。

  • b中乘积项的系数为1时,把该乘积项累积到答案中。

  • b&1运算可以取出b在二进制表示下的最低位,而b>>1运算可以舍去最低位,在递推过程中就可以遍历b中每个乘积项的系数。

  • 时间复杂度O(log2b)

代码

int power ( int a, int b, int p){
    int res = 1 ;
    while( b != 0){
        if(b & 1 == 1){
            res = (long)res * a % p;  //如果系数为1,乘进结果里
        }
        a = (long)a * a % p;      //计算第k位对应的指数a
        b >>= 1;            //右移一位舍去最低位
    }
    return res;
}

练习

看完以上快速幂的神奇运算,你是不是惊讶到了呢。

快来趁热打铁练习练习吧。

abp 取模的值,其中1<=a,b,p<=10^18。

lowbit运算

lowbit(n)定义为非负整数n在二进制表示下“最低为的1及起后边所有的0”构成的数值。例如 n=10的二进制表示位(1010)2,则 lowbit(n)=2=(10)2

推导公式:

n>0,n的第k位是1,第0~k-1位都是0

为了实现lowbit运算,先把n取反,此时第k位变为0,第第0~k-1位都是1。再令n=n+1,此时因为进位,第k位变为1,第0~k-1位都是0

在上面的取反加1操作后,n&(~n+1)仅有第k位为1,其余位0。而上文中提到补码 -n = ~n+1,因此有:

妙用lowbit

lowbit运算可以找出整数二进制表示下为1的位数,且时间复杂度为O(1)

我们只需不断把n赋值为n - lowbit(n),直至n=0

例: n = 9 =(1001)2 则 lowbit(n) =1,把n赋值为 n - lowbit(n)

即为 9- lowbit(9) = 8 =(1000)2 则lowbit(8) = 8 =(1000)2,此时n=0。

状态压缩

二进制状态压缩,是指将一个长度为m的bool数组用一个m位二进制整数并存储的方法。利用下列位运算操作可以实现原bool数组对应下标元素的存取。

操作运算
取出整数n在二进制表示下的第k位(n>>k) & 1
取出整数n在二进制表示下的第0~k-1位(后k位)n & ((1<<k)-1)
把整数n在二进制表示下的第k位取反n xor (1<<k)
对整数n在二进制表示下的第k位赋值1n | (1<<k)
对整数n在二进制表示下的第k位赋值1n & (~(1<<k))

补充

怎么样,看完了本文章是不是感觉功力大增呢,快去leetcode做一做练习修炼一下内功。

今天很开心,因为解锁了leetcode题数破百成就哦。快来跟我一起竞争吧!!

中等题的数量还很少,还要继续加油呀!

刷题之路,任重而道远。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值