题目链接:hdu 5014
给出一个从0到n的全排列数组a,求一个对应的数组使得,a[i]^b[i]的总和最大,输出总和并输出b数组
要使得异或值最大,就要让每个数的1尽量加进计数中,因此对于每个数a,要找到匹配数b使得两者的异或值为两者的和
从最高位n开始向0找每个数的匹配数,对于数a,若该数尚未匹配,则找数b使得a+b的值为2^x-1,(x为a的二进制位数),最大和即为0~n的总和的两倍
/******************************************************
* File Name: 1008.cpp
* Author: kojimai
* Creater Time:2014年09月14日 星期日 13时25分56秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 100005
int match[FFF];
int val[FFF];
int a[FFF];
void init()
{
val[1]=1;
for(int i = 2;i <= 17; i++)
{
val[i]=(val[i-1]+1)*2-1;
}
return;
}
int qfind(int x)
{
int l=1,r=17,mid;
while(l<=r)
{
mid=(l+r)/2;
if(val[mid]>x)
{
r=mid-1;
}
else
l=mid+1;
}
return l;
}
int main()
{
int n;
init();
while(~scanf("%d",&n))
{
memset(match,-1,sizeof(match));
long long all=0;
for(int i=0;i<=n;i++)
{
scanf("%d",&a[i]);
all+=a[i];
}
all*=2;
int t=qfind(n);
for(int i=n;i>=0;i--)
{
if(match[i]==-1)
{
if(i==0)
{
match[0]=0;
break;
}
while(i<=val[t-1])
t--;
match[i]=val[t]-i;
match[val[t]-i]=i;
}
}
cout<<all<<endl;
//long long debug=0;
for(int i=0;i<=n;i++)
{
//debug+=match[a[i]];
if(i==0)
printf("%d",match[a[i]]);
else
printf(" %d",match[a[i]]);
}
cout<<endl;
//cout<<"debug = "<<debug<<endl;
}
return 0;
}