题意:
给出一个由0-n这n+1个数字组成的序列;
要求你给出另一个序列有0-n组成,让他们一一对应 异或相加的值最大;
输出最大值,和你给出的序列;
思路:
异或完要得到最大值,就应该要二进制是互补的,如10110^01001;
我们的最大值是n,所以我们首先要找到和n互补的值是多少,例如找到是c和n互补;
那么n-1和c+1互补;n-2和c+2也互补;类推;
然后在用c-1作为最大值递归;
至于怎么找到和n互补;
如10110,那么我先算出它小于等于哪个2的次方;即100000;
然后把n取反得到;11111..01001(最后5位取反了,前面都是1)
和(100000-1)做and,这样就保留最后5位,剩下置0;
(做这道题时hdu抽风了,交上去全是超时,一直修修改改好久不知道为什么,后来把别人A的代码交上去也是超时..满脸黑线..)
AC
#include<cstdio>
#include<cstring>
const int N = 1e5 + 10;
int sum;
struct uni{
int x,y;
}u[N];
int m[N],num[N],n;
void f(int x) {
if(x == 0) {
m[0] = 0;
return;
}
int cur = 1;
int c;
for(int i = 0; ; i++) {
if(x <= cur)
break;
cur *= 2;
}
c = ~x & (cur - 1);
for(int i = x,j = c; i > j; i--,j++) {
m[i] = j;
m[j] = i;
}
if(cur != 0)
f(c - 1);
}
int main() {
while(~scanf("%d",&n)) {
sum = 0;
for(int i = 0; i <= n; i++) {
scanf("%d",&num[i]);
}
f(n);
printf("%d\n",(1 + n) * n / 2);
for(int i = 0; i <= n; i++) {
if(i)
printf(" ");
printf("%d",m[num[i]]);
}
printf("\n");
}
}