简单二进制操作--lowbit

简单的二进制操作lowbit运算

lowbit运算是一种常用的二进制运算操作,它的作用是返回某个数的二进制表示中最末一个1及其后边的0构成的十进制数大小。

如: 假设x = 1000100010 -- lowbit(x) = 10(2进制)=2(10进制)

那么具体lowbit操作要怎么实现呢,其实很简单,直接返回 x & -x 即可,因为假如x为正,那么-x<0。因为计算机底层对整数的存储是基于补码的。所以,如果大家稍微有点数据逻辑或这计组基础的话。x的补码就是1000100010(正数三码合一),-x的补码就是0111011110(负数的补码等于x取反+1),到此,我们得到了x和-x的补码表示,那么(x&-x)= 0000000010 = 2(10进制)。

上述简单的阐述可以佐证lowbit的正确性。既然它的正确性有了保证,那么它到底有什么用呢?

下面我们举一个最最简单的lowbit运算的应用场景:求一个十进制数的二进制表示中有几个1。如 10(10进制)的二进制表示就有2个1。

分析:要怎么可以得到我们想要的答案2呢?我们可以使用lowbit运算来得到某个数的最末位的1及其后边的0构成的数,然后使用原数减去这个lowbit求得的数,那么原数就会减少一个1,我们可以统计一共减少1的次数,直到原数变为0.

题目描述:给定一个长度为 n 的数列,请你求出数列中每个数的二进制表示中 1 的个数。

输入格式

第一行包含整数 n。

第二行包含 n 个整数,表示整个数列。

输出格式

共一行,包含 n 个整数,其中的第 i 个数表示数列中的第 i 个数的二进制表示中 1 的个数。

数据范围

1≤n≤100000 0≤数列中元素的值≤10^9

输入样例:

 5
 1 2 3 4 5

输出样例:

 1 1 2 1 2

下面是code展示:

 #include<cstdio>
 #include<cstring>
 #include<iostream>
 #include<algorithm>
 using namespace std;
 const int N = 1e5 + 10;
 int n;
 int lowbit(int x){
  return x&-x;
 }
 int main(){
  scanf("%d",&n);
  while(n--){
  int x,res=0;
  scanf("%d",&x);
  while(x) x-=lowbit(x),res++;
 
  cout<<res<<" ";
  }
  return 0;
 }

这就是lowbit运算最简单的应用了,除外,lowbit运算在线段树、树状数组中也有重要应用场景.

 

posted @ 2021-04-05 14:23  how_you_make_me_feel  阅读(288)  评论(0编辑  收藏  举报