思路:
对于每一个数字的二进制是唯一的,所以他的反也是唯一的(除符号位)。这样0 ^ 1 = 1 可以使的所有数字取得最大值。
(之前写的时候判断了 下是否有重复的,看了下网上代码发现想多了。。)
每次对于一个数字找到他的按位反,并且记录映射关系。最后输出即可。注意每次操作可以确定 两个数 3-->4 同时4->3也就随之确定了。ans注意*2
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
typedef long long ll;
ll a[100010];
ll b[100010];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(b,-1,sizeof(b));
ll ans=0;
for(int i=0;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(int i=n;i>=0;i--)
{
if(b[i]!=-1)
continue;
ll t=0;
for(int j=0;;j++)
{
if(!(i&(1<<j)))
t+=1<<j;
if(t>i)
{t-=1<<j;
break;
}
}
ans+=2*(i^t);
// cout<<i << " "<<(i^t) <<endl;
b[t]=i;
b[i]=t;
}
printf("%lld\n",ans);
for(int i=0;i<=n;i++)
{
printf(i==n?"%lld\n":"%lld ",b[a[i]]);
}
}
return 0;
}