位运算符:将数据看成二进制数运算。
运算符 | 符号 | 备注 |
---|---|---|
双目运算符 | 按位与& | 1 & 1 = 1 , 1 & 0 = 0 , 0 & 0 = 0 |
双目运算符 | 按位或| | 1 | 1 = 1 , 1 | 0 = 1 , 0 | 0 = 0 |
双目运算符 | 按位异或^ | 相同为1 , 不同为0 |
双目运算符 | 右移运算符>> | x >> n , x 右移 n 位 |
双目运算符 | 左移运算符<< | x << n , x 左移 n 位 |
单目运算符 | 按位反~ | 各二进位均按位求反 |
下列情况相等:
快 | 慢 |
---|---|
x >>= 1 | x /= 2 |
查看未知 2 进制数 a 的第 b 个数 x
x = (a >> b) & 1;
题目描述:
给出一个整数n,请求出1-n之间选取两个数进行异或最大能得出多大?
(两个数可以相同)1 ≤ N ≤10^18
题目思路:n 的二进制数全为1,则最大。
#include<iostream>
using namespace std;
int main(){
long long n, ans = 0; // ans为答案的二进制数
cin >> n;
while(n){
ans <<= 1; // 左移加一位
ans |= 1; // 若为 0 则变为 1
n >>= 1; // n 右移一位,ans 与 n 最后位数相等
}
cout << ans << endl;
return 0;
}
异或 ^
0 ^ n = n
n ^ n = 0
满足交换律、结合律
a ^ b = b ^ a
a ^ (b ^ c) = (a ^ b) ^ c
交换a甲
和b乙
的值(前提不是指向同一地址)
a = a ^ b; // a = 甲 ^ 乙,b = 乙
b = a ^ b; // a = 甲 ^ 乙,b = 乙 ^ 甲 ^ 乙 = 甲 ^ 0 = 甲
a = a ^ b; // a = 甲 ^ 乙 ^ 甲 = 乙,b = 甲
题目:
(1)数组中有一个数出现奇数次,其他数出现偶数次,求出现奇数次的数是什么数?
#include<bits/stdc++.h>
using namespace std;
void Oddnum2(int arr[], int size) {
int eor = 0;
for(int i = 0; i < size; i++) {
eor ^= arr[i];
}
printf("%d\n", eor);
}
int main() {
int n, *arr;
cin >> n;
arr = new int[n]; //动态内存分配
for(int i = 0; i < n; i++) cin >> arr[i];
Oddnum2(arr, n);
delete []arr; //释放
return 0;
}
(2)数组中有两个数出现奇数次,其他数出现偶数次,求出现奇数次的两个数分别是什么数?设其一为a,其二为b。
#include<bits/stdc++.h>
using namespace std;
void Oddnum2(int arr[], int size) {
int eor = 0;
for(int i = 0; i < size; i++) {
eor ^= arr[i];
} // eor = a ^ b 且 != 0
int right = eor & (~eor + 1); // 右1
int someone = 0;
for(int cur = 0; cur < size; cur++) {
if((someone & right) == 0) someone ^= cur; // ==0 或 someone
} // someone 为 a 或 b
printf("%d %d\n", someone, (eor ^ someone));
}
int main() {
int n, *arr;
cin >> n;
arr = new int[n]; //动态内存分配
for(int i = 0; i < n; i++) cin >> arr[i];
Oddnum2(arr, n);
delete []arr; //释放
return 0;
}