题意给你一个序列,1---n,你安排另一个1---n的序列顺序,使得按位异或最后加起来和最大。。那么就是贪心高位,也就是从后往前了。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int a[100005];
int b[100005];
int n;
int fin(int x){
int temp=0;
int ret=0;
int i=0;
while(x){
temp=((x&1)^1);
ret=(temp<<i)+ret;
++i;
x/=2;
}
if(b[ret]==-1){
return ret;
}
else{
return -1;
}
}
void init(){
for(int i=n-1;i>0;i--){
if(b[i]!=-1)
continue;
int x=fin(i);
if(x!=-1){
b[i]=x;
b[x]=i;
}
}
return;
}
int main(){
while(cin>>n){
n++;
memset(b,-1,sizeof(b));
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
init();
long long ans=0;
if(n%2==1)
b[0]=0;
for(int i=0;i<n;i++){
ans+=(a[i]^b[a[i]]);
}
cout<<ans<<endl;
for(int i=0;i<n;i++){
if(i!=n-1)
printf("%d ",b[a[i]]);
else
printf("%d
",b[a[i]]);
}
}
return 0;
}
这题做的时候略坑了。。。一眼看出贪心然后发现又遇到了问题,一下写不出来了。。第二天吧n是偶数的时候用next_permutation打表爽了一下。发现n是偶数的时候0异或0剩下贪心一下依旧是,于是从后往前贪心一下,按位取反一下,用到 ((x&1)^1) 再把每次新求到的位放到前面就行了 。代码如下: