lowbit(二进制中1的个数)
作者:
qushuka
,
2022-01-25 16:27:42
,
所有人可见
,
阅读 304
//使用lowbit操作,进行,每次lowbit操作截取一个数字最后一个1后面的所有位,
//每次减去lowbit得到的数字,直到数字减到0,就得到了最终1的个数,O(nlogn)
/*为了实现lowbit运算,先把n取反,此时第k位变为0,第0~k-1位都是1。再令n=n+1,此时因为进位,
第k位变为1,第0~k-1位都是0.
在上面的取反加1操作后,n的第k+1到最高位恰好与原来相反,所以n&(~n+1)仅有第k位为1,其余位都是0.
而在补码表示下,~n=-n-1,因此:lowbit(n)=n&(~n+1)=n&(-n);
为什么~n=-n-1
1 负数的补码是对其原码逐位取反,但符号位除外;然后整个数加1
2 求-7的补码:因为给定数是负数,则符号位为“1”。
后七位:-7的原码(10000111)→按位取反(11111000)(负数符号位不变)→加1(11111001)
所以-7的补码是11111001。
再如一个数字原码是10001000,他的负数表示形势是补码,
就是反码+1,反码是01110111,加一则是01111000,二者按位与得到了1000,就是我们想要的lowbit操作
*/
#include<iostream>
using namespace std;
int lowbit(int x){
return x&(-x);
}
int main(){
int n;
cin>>n;
while(n--){
int x;
cin>>x;
int ans=0;
while(x){
x-=lowbit(x);
ans++;
}
cout<<ans<<" ";
}
return 0;
}
/*对于每个数字a,a&1得到了该数字的最后一位,之后将a右移一位,直到位0,就得到了1的个数
#include<iostream>
using namespace std;
int n;
int a,k;
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a);
k=0;
while(a){
k+=a&1;
a=a>>1;
}
printf("%d ",k);
}
return 0;
}
*/