题目大意:给定一个数值n,并且[0,n]之间的n+1个数组成一个数列a,求出一个与之对应位的异或值之和最大的一个数列b,b取值为[0,n]。
解题思路:若使两个数a,b异或值最大,b只需满足异或之后将a的二进制位为0的位置变为为1,且b的二进制位的最高位不能超过a。
题目来源:点击打开链接
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxn 100001
int a[maxn],b[maxn];
long long ans;
int main()
{
int n,t,j,res;
while(~scanf("%d",&n))
{
ans = 0;
memset(b,-1,sizeof(b));
for(int i = 0; i <= n; i++)
{
scanf("%d",&a[i]);
ans +=a[i];
}
ans<<=1;
printf("%I64d\n",ans);
for(int i = n; i >= 0; i--)//
if(b[i] == -1)//
{
t = i, j = 1, res = 0;//首先对[0,n]之间的每个数求与之异或值最大的数值;
while(t)//
{
if(t&1);//如果t为奇数,则证明此时的最高二进制位不为0;
else
res |= j;//当t为偶数时,证明1xj(j转换成2^k形式)的位置为0,此时要进行异或;
j<<=1,t>>=1;//每次进行完异或运算后,t的二进制位就要向右移动一位,进行判定,而j要向左移动一位,等待填补空缺;
}
b[res] = i, b[i] = res;
}
for(int i = 0; i < n; i++)
printf("%d ",b[a[i]]);
printf("%d\n",b[a[n]]);
}
return 0;
}
以上分析也许不是很详细,毕竟还是菜鸟,望请谅解!