位运算我们主要学了六种:按位与(&),按位或(|),按位异或(^),按位取反(~),左移(<<),按位右移(>>)。
我们先来看一道问题,求n在二进制上求第k个数字是几?
我们给一个万能的公式:n >> k &1
我们来解释一下:先看一个例子:将10转换为二进制
#include <iostream>
using namespace std;
int main()
{
int n = 10;
for (int k = 3; k >= 0; k--)
{
cout << (n >> k & 1);//输出1010
}
return 0;
}
我们都知道10的二进制对应为1010,那么我们来看一下上述是怎么算的呢?我们知道循环先进去,n >> 3,就是把10右移三位,是1,1再与1按位与,得1;然后n >> 2,把10右移两位,是10,10再与1(01)按位与,得1;然后 n >> 1 ,把10右移一位,得101,101与1(001)按位与的001,得1;最后 n >> 0,得1010,与1(0001)按位与得0,最后输出的结果就是1010。
总结: 公式 n >> k & 1,就是计算数字n在二进制下第k位数字是几。
以前,我们都写过这么个问题,就是在屏幕上输入数字,算出它对应的二进制数字
- 将数字除以%(模运算符)2,并将余数存储在数组中
- 通过/(除法运算符)将数字除以2
- 重复步骤2,直到数字大于零
#include <iostream>
using namespace std;
int main()
{
int q[10], n, i;
cin >> n;
for (i = 0; n > 0; i++)
{
q[i] = n % 2;
n /= 2;
}
for (i = i - 1; i >= 0; i--)
{
cout << q[i];
}
cout << endl;
return 0;
}
我们再来看一个公式:求返回数字n在二进制中的最后一位1,: lowbit(n)= n & -n;
例如n = 1010,lowbit(n) = 10; n = 101000,lowbit(n )= 1000;
我们来讲一下为什么可以这样,我们必须要具备原码、反码、补码的知识,可以得到 x & (-x)= (~x + 1)
例如:
x = 1010…100…0
~x = 0101…011…1
~x+1 = 0101…100…0
x &(~x+1) = 0000…100…0
这样,我们就可以计算出数字n在二进制中的最后一位1;
示例:
题目要求:
给定一个长度为 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
#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 res = 0;
while (x) x -= lowbit(x), res++;//每次减去x的最后一位1
cout << res << ' ';
}
return 0;
}