题目来源:https://vjudge.net/problem/HDU-5014
【题意】
给出一个n,外加一个0-n无序序列(n+1个数),给出一个公式:
t=a[0]^b[0]+a[1]^b[1]+…+a[n]^b[n],让求t的最大值,其中b数组
也是从0-n,不过顺序的话是随意的,只要让t最大就行。
【思路】
异或,想到二进制,怎么使a[i]^b[i]最大,想到补位(纯属个人造词),
举个例子,10的二进制是1010,如果使他最大为1111,那么需要5,也就是101来进行补位。
分析样例,4 2 0 1 4 3,那么他们的二进制是 10 0 1 100 11,
从大到小依次替换,b序列是 1 0 10 11 100,刚好符合样例。
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<map>
#include<queue>
using namespace std;
typedef long long LL;
int a[100004];
int b[100004];
bool v[100004];
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(v,0,sizeof(v));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0; i<=n; i++)
scanf("%d",&a[i]);
for(int i=n; i>=0; i--)//从大到小依次替换
{
if(!v[i])//判断有没有被替换过
{
int pp=1,c,w=0,p=i;
while(p)//根据其二进制求其相应的数
{
c=p%2;p/=2;
if(!c) w+=pp; pp*=2;
}
v[i]=v[w]=1; b[i]=w;b[w]=i;//标记+替换
}
}
LL tmax=0;
for(int i=0; i<=n; i++)
tmax+=(LL)(a[i]^b[a[i]]);
printf("%lld\n",tmax);
printf("%d",b[a[0]]);
for(int i=1; i<=n; i++)
printf(" %d",b[a[i]]);
printf("\n");
}
}