概念
异或(x⊕y或x ^ y)
高低位交换:https://www.luogu.com.cn/problem/P1100
题意:给定一个32 3232位整数x xx,在二进制下交换其前16 1616位与后16 1616位,输出最终的数。
答案为ans = (x >> 16) | (x << 16)
注意此处使用32 3232位无符号整数进行计算,这样x << 16会自然溢出,导致前16 1616位被丢弃,恰好满足要求。
参考:
#include <cstdio>
using namespace std;
int main()
{
unsigned int x;
scanf("%u", &x);
printf("%u\n", (x >> 16) | (x << 16));
return 0;
}
位运算模板
求n的第k位数字: n >> k & 1
返回n的最后一位1:lowbit(n) = n & -n
1.求n的第k位数字 : n>>k&1 (n右移k位, 然后&1)
int n = 15; //00000000000000000000000000001111
for(int i=31;i>=0;i--){
System.out.print( n>>i & 1 ); //00000000000000000000000000001111
}
2.返回n的最后一位1 : lowbit(n) = n & -n 这里的 -n 也就是 ~n+1(取反加一)
public static int lowbit(int n){
return n & -n;
}
lowbit(x)即为二进制下x xx的最低位,如lowbit(10010) = 10、lowbit(1) = 1。严格来说0没有lowbit,部分情况下可视为lowbit(0) = 1。利用lowbit函数可实现树状数组等数据结构。
模板题
AcWing 801. 二进制中1的个数
输入样例:
5
1 2 3 4 5
输出样例:
1 1 2 1 2
思路 : 使用 lowbit(n) 依次算出每个末尾1的数 然后减去后继续 lowbit
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e5+10;
int a[N];
int b[N];
int lowbit(int x)
{
return x&(-x);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n;
cin>>n;
while(n--)
{
int x;
cin>>x;
int cnt=0;
while(x)
{
x-=lowbit(x);//减去最后一个1以及后面的数(二进制)
cnt++;
}
cout<<cnt<<" ";
}
}
位运算的应用
1.x & 1
一个数补码表示中的第k位数字
int func(int n, int k)
{
return ((n >> k) & 1);
}
求补码中含有1的个数
int func(int n)
{
int countn = 0;
while (n)
{
if (n & 1) countn++;
n = n >> 1;
}
return countn;
}
偶数位与奇数位分开输出
void func(int n)
{
std::cout << "奇数位输出:>";
for (int i = 31; i >= 1; i -= 2)
{
std::cout << ((n >> i) & 1) << ' ';
}
std::cout << std::endl << "偶数位输出:>";
for (int i = 30; i >= 0; i -= 2)
{
std::cout << ((n >> i) & 1) << ' ';
}
}
2.x & (-x)
返回x的最后一位1及之后的数字
lowbit(x):返回x的最后一位1及之后的数字
x=101000 lowbit(x)=1000
x=1010 lowbit(x)=10
判断一个数是否是2的n次方
bool func(int n)
{
return (n == (n & (-n)));
}
求补码中含有1的个数
int func(int n)
{
int countn = 0;
while (n)
{
countn++;
n -= (n & (-n));
}
return countn;
}
3.x & (x - 1)
求补码中含有1的个数(微软)
int func(int x)
{
int countx = 0;
while (x)
{
countx++;
x = x & (x - 1);
}
return x;
}
判断一个数是否是2的n次方
bool func(int x)
{
x = x & (x - 1);
return x ? false : true;
}
两个数补码位上不同数的数量
int func(int x, int y)
{
int ret = x ^ y, count = 0;
while (ret)
{
count++;
ret = ret & (ret - 1);
}
return count;
}