题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014
题意:给定数列以及数列值的范围,求该范围内另一个数列,使得两个数列对应位的异或和最大。
思路:从n到0贪心即可,要是异或和最大,那么叫二进制每一位都是是1,也就是两个数字对应为相反的数,比如1001,和0110异或和就是1111,所以对于每一个数字,先判断他是几位二进制,然后减去1,就是他所在位都是1的二进制数,这个数字与他本身异或,那么就变成了和他相反的数字,比如1111^1001=0110,0110这个数字就是咱们所需要的对应的数字,同样0110这个数字对应的数字也就是1001,这样遍历一遍,就找到了对应的数字
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 100005;
int a[maxn];
int b[maxn];
int num(int i)
{
int k=0;
while(i)
{
i=i/2;
k++;
}
return k;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0; i<=n; i++)
{
scanf("%d",&a[i]);
}
memset(b,0,sizeof(b));
for(int i=n; i>=0; i--)
{
if(!b[i])
{
int k=((1<<num(i))-1)^i;
b[i]=k;
b[k]=i;
}
}
printf("%I64d\n",(ll)n*(n+1));
for(int i=0; i<=n; i++)
{
if(i!=n)
printf("%d ",b[a[i]]);
else
printf("%d\n",b[a[i]]);
}
}
return 0;
}