对于从N到0的每个数a,找到与他互补的那个数就是应该和他异或的数b。
互补就是说,把a写成二进制,那么a是0的位b对应的要是1,a是1的位b对应的要是0。eg 1010和0101。
不难发现,不会存在两个数同时对应同一个互补的数。
从大到小求互补的数是因为,如果从小到大求的话,比如求00001,还要根据N判断他是和11110互补还是和11111111111110互补很麻烦。
#include <iostream>
#include<stdio.h>
#include<cstring>
#define N 100010
using namespace std;
int a[N];
int b[N]; //N所对应的b值
__int64 ans;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(b,-1,sizeof b);
for(int i = 0 ; i <= n;i++) scanf("%d",&a[i]);
for(int i = n;i >= 0;i--)
{
int cur = i;
int num = 0;
int cnt = 1;
if(b[cur] == -1) //还没有算过其值
{
while(cur)
{
int tmp = cur%2;
if(tmp == 0) num+=cnt;
cnt*=2;
cur>>=1;
}
b[i] = num;
b[num] = i;
}
}
ans = 0;
for(int i = 0 ; i <= n;i++) ans+=a[i]^b[a[i]];
printf("%I64d\n",ans);
int flag = 0;
for(int i = 0 ; i <= n;i++)
{
if(flag) printf(" ");
printf("%d",b[a[i]]);
flag = 1;
}
printf("\n");
}
return 0;
}