十进制转二进制:
十进制转 k 进制:
将十进制数 n 转换为 k(k≤35) 进制数。(注:如果某个数字 r≥10 则使用字符 'A' + (r - 10)
代替)
char digit[25];
void change(int n, int k) {
int m = 0;
while (n) {
int r = n % k;
if (r < 10) {
digit[m++] = '0' + r;
} else {
digit[m++] = 'A' + (r - 10);
}
n /= k;
}
digit[m] = '\0';
for (int i = 0, j = m - 1; i < j; i++, j--) {
swap(digit[i], digit[j]);
}
}
二进制转十进制:
k 进制转十进制:
将 k 进制数 dight
(使用字符数组存储),转换为十进制数。
int change(char digit[25], int k) {
int n = 0;
int len = strlen(digit);
for (int i = 0; i < len; i++) {
if (digit[i] <= '9') {
n = n * k + (digit[i] - '0');
} else {
n = n * k + (digit[i] - 'A');
}
}
return n;
}
位运算
计算机中所有的数据都是以二进制的形式存储的,即 0,10,1 两种状态,计算机对二进制数据进行的运算被称为位运算。
3&5
的值得 1。
0 0 0 0 0 0 1 1
& 0 0 0 0 0 1 0 1
——————————————————
0 0 0 0 0 0 0 1
3|5
的值得 7 。
0 0 0 0 0 0 1 1
| 0 0 0 0 0 1 0 1
——————————————————
0 0 0 0 0 1 1 1
3^5
的值得 66 。
0 0 0 0 0 0 1 1
^ 0 0 0 0 0 1 0 1
——————————————————
0 0 0 0 0 1 1 0
异或的性质
快速记忆法:相同为 0,不同为 1。
1^1 = 0
1^0 = 1
0^1 = 1
0^0 = 0
可以发现 00 异或任何数后,都等于该数本身,例如 (11)_2(11)2 ^ (00)_2 = (11)_2 = (3)_{10}(00)2=(11)2=(3)10。
(重要)根据这个性质,我们可以得出结论:a^b^b
的结果等于a
。因为两个 b 异或后等于 0 了,0 异或 a 等于 a
例题:最大异或和
蒜头君有一个长度为 n 的非负整数数列 ai。
现在给出一个正整数 mm,蒜头君需要找到一个非负整数 k,满足 k<2m,并且使得数列 aa 的所有数的异或和再与 k 异或的结果最大,即a1⊕a2⊕⋯⊕an⊕k 的结果最大。
输出最大的异或和。
注:yx⊕y 表示的是 x 异或 y,在 C++ 中异或使用^
符号。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int a[maxn];
int solve(int x, int m) {
int bit[35] = {0};
for (int i = 0; x != 0; i++) {
bit[i] = x % 2;
x /= 2;
}
for (int i = 0; i < m; i++) {
bit[i] = 1;
}
int ans = 0;
for (int i = 30; i >= 0; i--) {
ans = ans * 2 + bit[i];
}
return ans;
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int x = 0;
for (int i = 1; i <= n; i++) {
x ^= a[i];
}
cout << solve(x, m) << endl;
return 0;
}