位运算有好多应用,限于篇幅 懒呐 这里只列举了一部分,整理好再补充
1.交换两个数(不需额外变量)
#include<iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
int x, y;
cin>>x>>y;
x = x ^ y;
y = x ^ y;
x = x ^ y;
cout<<x<<' '<<y"\n";
return 0;
}
PS:x^x=0; x^0=x;
PPS:其实不借助额外变量还有另一种方法 当然这是题外话
x = x + y;
y = x - y;
x = x - y;
2.判断一个数是否为2的幂次方
如果一个数是2的幂次方,那么这个数的二进制数中有且仅有一个1,其余为0,将这个数减去1得到的值的二进制数1变成0,1之后的0,全部变成1,显然,两数做与运算的结果为0,由这个结论即可判断一个数是否为2的幂次方。代码如下:
int judge(int n){
return n & (n - 1);
}
PS:128 :1000 0000
127 :0111 1111
3.判断一个数是否为偶数
如果一个数是偶数,那么这个数的二进制数的最后一位为0,和1做与运算结果为0,反之,结果为1.
if(n & 1 ) {
// n为奇数
}
多数时候判断奇偶性的代码如下:
if(!(n % 2)) {
//n为奇数
}
但是位运算更快
4.找出不重复的数 今天的重头戏
x ^ y ^ y = x;
- 例题1找筷子
题目描述
经过一段时间的紧张筹备,电脑小组的“RP餐厅”终于开业了,这天,经理LXC接到了一个定餐大单,可把大家乐坏了!员工们齐心协力按要求准备好了套餐正准备派送时,突然碰到一个棘手的问题,筷子!CX小朋友找出了餐厅中所有的筷子,但遗憾的是这些筷子长短不一,而我们都知道筷子需要长度一样的才能组成一双,更麻烦的是CX找出来的这些筷子数量为奇数,但是巧合的是,这些筷子中只有一只筷子是落单的,其余都成双,善良的你,可以帮CX找出这只落单的筷子的长度吗?
输入格式
第一行读入一个数N,它代表CX找到的筷子的根数。
第二行是N个用空格隔开的数,代表筷子的长度。
输出格式
一行,落单的筷子的长度。
输入输出样例
输入 #1
9
2 2 1 3 3 3 2 3 1
输出 #1
2
说明/提示
对于60%的数据,N<=100001;
对于100%的数据,N<=10000001,筷子长度不大于 10^9。
内存限制4MB
分析:首先可以发现内存限制,所以最简单直接的桶排就不太友好,而这题如果用位运算的话,完全不用担心内存问题啦。话不多说,上代码。
#include<iostream>
int main() {
std::ios::sync_with_stdio(false);
int n, t, x;
std::cin>>n;
for(int i = 0; i < n; ++i){
std::cin>>x;
t ^= x;
}
std::cout<<t<<"\n";
}
- 例题2只出现一次的数
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3
示例 2:
输入: [0,1,0,1,0,1,99]
输出: 99
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/single-number-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
#include<stdio.h>
int x, sum, a[32];
int main() {
while(~scanf("%d", &x)) {
if(!x) continue;
for(int i = 0; i < 32; ++i) {
a[i] += ((x>>i) & 1);
}
}
for(int i = 0; i < 32; ++i) {
if(a[i] % 3 != 0) {
sum +=(1 << i);
}
}
printf("%d",sum);
}
- 例题3.号码游戏
题目背景
这一天学校组织了一个游戏,找找谁才是倒霉蛋。
题目描述
分别让n个人每个人都拿一个号码a[i] (i < n && a[i] < 2^31),每两个人之间相互看号码,如果号码相同的话就可以一起出去,否则还必须接着看其他人的,这个游戏保证最后1个人或者2个留下来。
输入格式
第一行两个数 n,k (n≤3000000,1≤k≤2),n表示参加游戏的人数,接下来 n行每行一个正整数表示游戏上每一个人的密码,k表示最后留在游戏的人数。
输出格式
从小到大输出一行 k个数,表示最后留在游戏里的倒霉蛋,中间用空格分隔.
输入输出样例
输入 #1
3 1
2 2 2
输出 #1
2
#include<iostream>
using namespace std;
const int N = 3e6 + 6;
int a[N];
int re[2];
int main() {
ios::sync_with_stdio(false);
int n, k, x, t;
cin>>n>>k;
if(k==1) {
for(int i = 1; i <= n; ++i) {
cin>>x;
t ^= x;
}
cout<<t;
}else {
for(int i = 1; i <= n; ++i) {
cin>>a[i];;
t ^= a[i];
}
t &= -t;
for(int i = 1; i <= n; ++i) {
if((t & a[i]) != 0) {
re[0] ^= a[i];
}else {
re[1] ^= a[i];
}
}
if(re[0] > re[1]) swap(re[0], re[1]);
cout<<re[0]<<' '<<re[1];
}
return 0;
}