HDU - 5014 Number Sequence(贪心+位运算)

来源:互联网 发布:win10获取权限软件 编辑:程序博客网 时间:2024/05/16 17:13
Number Sequence
Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u

[Submit]   [Go Back]   [Status]  

Description

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

● a i ∈ [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,...,bn. 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

42 0 1 4 3
 

Sample Output

201 0 2 3 4
 

题目大意:
有一个a集合满足
● a i ∈ [0,n] 
● a i ≠ a j( i ≠ j ) 

同样的b也满足该规则,
现在问你是否存在一个序列b,使得t最大

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

n(1 ≤ n ≤ 10 5)


解析:贪心题,但是比赛时候我用的是回溯求解该题,一直超时。后来想想我太笨了如果用回溯的话复杂度为O(10^10),太大了。

其实弄清楚了这题的思路敲起来还是蛮简单的,每一个数的最大的异或是和他互补的数。10101^01010最大,如果全部都取最大,那么最后的t肯定最大。

那么一个数的互补怎么求呢? 就是这个数 异或上 与该数二进制位数相同,且都为1的数

       1010

xor  1111

       0101

弄清楚这个就好办了。求出所有数的互补,把它存入一个数组中,最后按照输入时的顺序输出该数组,就好了。

注意:Hdu有个比较坑的地方,就是不能开成long long 所以应该把t 声明为__int64才能过,坑爹啊。


#include<cstdio>#include<cstring>#include<cmath>using namespace std;typedef __int64 LL;const int MAX = 100005;int a[MAX],ans[MAX],vis[MAX];int main() {int n;while(scanf("%d",&n)!=EOF) {for(int i = 0;i <= n;++i)scanf("%d",&a[i]);memset(vis,0,sizeof(vis));memset(ans,0,sizeof(ans));for(int i = n;i > 0;--i) {if(vis[i])continue;int d = log2(i)+1;int temp = ((1 << d) - 1)  ^ i;ans[i] = temp;ans[temp] = i;vis[temp] = vis[i] = 1;}LL sum = 0;for(int i = 0;i <= n;++i)sum += (LL)(i ^ ans[i]);printf("%I64d\n",sum);for(int i = 0;i < n;++i)printf("%d ",ans[a[i]]);printf("%d\n",ans[a[n]]);}return 0;}


0 0
原创粉丝点击