题意:
给出一个由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"); } }
原文地址:http://blog.csdn.net/yeyeyeguoguo/article/details/44204717