Number Sequence (思维,二进制)

题目来源: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
#include
#include
#include
#include
#include
#include
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");
    }
}

你可能感兴趣的:(ACM竞赛,【含有数学思想】,【含有一定技巧】,【含有一定思考】,ACM的进程)