Number Sequence

There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules:

● a i 0,n 0,n
● a i ≠ a j( i ≠ j )

For sequence a and sequence b, the integrating degree t is defined as follows(“�” denotes exclusive or):

t = (a 0 � b 0) + (a 1 � b 1) +・・・+ (a n � b n)


(sequence B should also satisfy the rules described above)

Now give you a number n and the sequence a. You should calculate the maximum integrating degree t and print the sequence b.
Input
There are multiple test cases. Please process till EOF.

For each case, the first line contains an integer n(1 ≤ n ≤ 10 5), The second line contains a 0,a 1,a 2,...,a n.
Output
For each case, output two lines.The first line contains the maximum integrating degree t. The second line contains n+1 integers b 0,b 1,b 2,...,b n. There is exactly one space between b i and b i+1 (0 ≤ i ≤ n - 1). Don’t ouput any spaces after b n.
Sample Input
4
2 0 1 4 3
Sample Output
20
1 0 2 3 4
  
  
题意:求[ 0 , n]的两个排列两两异或和的最大值
思路:算的上是一道规律题吧,拿 5 101 来说,能异或到的最大的数是 111 ,那么就有( 101 10 )和( 100 11 )这两种,那么我们依次推下去求解
就是比如: 0 1 2 3 4 5 对应的值是: 1 0 5 4 3 2。。我们通过样例会发现,a数组的数的二进制取反之后的十进制就是结果
#include<stdio.h>
#include <iostream>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<map>
#include<vector>
#include<deque>2
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
int a[100001];
int b[33];
int s[100001];
int vis[100001];
int we(int n)
{
    memset(b,0,sizeof(b));
    if(n==0)
        return 0;
    else
    {
    int p=0;
    while(n)
    {
        b[p++]=n%2;
        n/=2;
    }
    ll sum=0;
    ll ans=1;
    for(int i=0; i<p; i++)
    {
        if(b[i]==0)
        {
            sum+=ans;
        }
        ans*=2;
    }
    return sum;
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        for(int i=0;i<n+1;i++)
            scanf("%d",&a[i]);
            ll sum1=0;
            memset(vis,0,sizeof(vis));
        for(int i=n;i>=0;i--)
        {
            if(vis[i]==0)
            {
           s[i]=we(i);
           s[we(i)]=i;
           vis[i]=1;
           vis[we(i)]=1;
            }
        }
        for(int i=0;i<n+1;i++)
        {
            sum1+=a[i]^s[a[i]];
        }
        printf("%lld\n",sum1);
        for(int i=0;i<n;i++)
        {
            printf("%d ",s[a[i]]);
        }
        printf("%d\n",s[a[n]]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值