时间限制 | 内存限制 |
---|---|
1000 ms |
65536 KB |
# 题目描述
De 在早八神游之中获得了一串传说中的异或数组。
该数组由 个元素 组成,De 需要通过该数组在白日梦境中找到一个长度同样为 的数组,其中每个数 满足 ,同时需要使 尽可能大才能得到仙人指路。
De 找到了认真上早八的你,希望你可以帮助他找到修仙之路。
# 输入格式
多组输入,每组输入两行。
第一行一个整数 ,满足 。
第二行输入 个整数 满足 。
# 输出格式
对于每组输入,输出一个整数表示满足条件的最大数。
# 输入样例
3 | |
2 2 2 | |
8 | |
7 4 12 33 6 8 3 1 |
# 输出样例
3 | |
47 |
# 题解:位运算 + 贪心
还是同样的套路,对于位运算使结果最大的问题,我们从高位到低位依次考虑,尽可能地让高位为 。
从最高位开始,我们统计所有数中这一位是 的数的个数。如果没有数这一位是 ,那么我们答案取不到 了,否则就会有某个 。如果只有一个数这一位是 ,那么显然 这一位取 ,答案这一位能保证是 ,但我们还要接着往下看,因为我们还不能保证某个 后面的所有取法都能使 。如果这一位有多个数是 ,那很显然,让其中一个数的 这一位取 ,其余数这一位取 ,对于接下来的所有位,令其余数中的一个数的所有位全部取 ,显然这个 ,再让其余 个数之后的所有位全部取 ,也一定不会超出 ,同时我们的答案也保证了最大。
时间复杂度:,其中 为数据组数。
参考代码:
#include <stdio.h> | |
int n, x[55]; | |
int main() | |
{ | |
// freopen("C.in", "r", stdin); | |
// freopen("C.out", "w", stdout); | |
while (~scanf("%d", &n)) | |
{ | |
for (int i = 1; i <= n; ++ i) | |
scanf("%d", &x[i]); | |
int ans = 0; | |
for (int i = 29; ~i; -- i) | |
{ | |
int cnt = 0; | |
for (int j = 1; j <= n; ++ j) | |
if (x[j] >> i & 1) | |
++ cnt; | |
if (cnt == 1) | |
ans |= 1 << i; | |
else if (cnt > 1) | |
{ | |
ans |= (1 << i + 1) - 1; | |
break; | |
} | |
} | |
printf("%d\n", ans); | |
} | |
return 0; | |
} |