目录
一、常用的位运算算法:
1.判断十进制转化为二进制后第k位上的数字是0还是1
代码:n >> k & 1
解释:共分为两步
①首先将数字 n 的第 k 位移到最后一位 :n>>k
②再将其与1取位运算& :&1 (若第k位为1则与1取&后即为1,否则为0)
将两步合并即为 :n>>k&1
2.取二进制最后一个1,用于求n中1的个数
代码:n & -n
解释:电脑存的是二进制的补码,正数的补码是它本身,负数的补码是原码按位取反再加一
01010的最后一个 1 为 10
0101000的最后一个 1 为 1000
举例:
十进制数 10,对应的二进制原码为 01010(首位0表示正数)
十进制数-10,对应的二进制原码为 11010(首位1表示负数)
11010的按位取反为:10101,再加一为:10111,两者取位运算:
01010
&
10111
=
00010
所以最后结果为10,即为十进制数 10 转化为二进制后最后一个1
二、AcWing--801.二进制中1的个数(位运算)
原题:
给定一个长度为 n 的数列,请你求出数列中每个数的二进制表示中 1 的个数。
输入格式
第一行包含整数 n。
第二行包含 n 个整数,表示整个数列。
输出格式
共一行,包含 n 个整数,其中的第 i 个数表示数列中的第 i 个数的二进制表示中 1 的个数。
数据范围
1≤n≤100000,
0≤数列中元素的值≤10输入样例:
5 1 2 3 4 5
输出样例:
1 1 2 1 2
运用上面的知识 2. 即可解决本题,代码如下:
//按位与&:同时都为1才是1,否则为0
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
int a;
cin>>a;
int s=0;
for(int i=a;i;i-=i&-i)
{
s++;
}
cout<<s<<' ';
}
}
三、知识补充:
1.将任意 2~36 进制转化为 10 进制
int Atoi(string s,int radix) // s是给定的radix进制字符串
{
int ans=0;
for(int i=0;i<s.size();i++)
{
char t=s[i];
if(t>='0'&&t<='9') ans=ans*radix+t-'0';
else ans=ans*radix+t-'a'+10;
}
return ans;
}
2.将10 进制数转化为任意 n 进制数,结果为char型
string intToA(int n,int radix) //n是待转数字,radix是指定的进制
{
string ans="";
do{
int t=n%radix;
if(t>=0&&t<=9) ans+=t+'0';
else ans+=t-10+'a';
n/=radix;
}while(n!=0); //使用do{}while()以防止输入为0的情况
reverse(ans.begin(),ans.end());
return ans;
}