zoukankan      html  css  js  c++  java
  • ACM学习历程——HDU 5014 Number Sequence (贪心)(2014西安网赛)

    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,b2,...,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
     
     

    这个题目想到贪心策略就好办了。

    最先想到的一种策略就是对于数k的二进制形式,把0换成1, 1换成0,亦或后将得到全1的最大数。而且每个数的0、1组合都是唯一的,自然其对应的那个数也是唯一的。

    但是会遇到一种情况,比如二进制1111和11111,它们都是和0亦或得到最大。

    于是这样考虑:

    对于任意一个数,只有两种情况,一是和比它小的数亦或,二是和比它大的数亦或。如果和比它小的数亦或,自然对应的数第一位肯定是0。后面可能会跟若干个0,最坏是1111这种,对应的是0;如果和比它大的数亦或,会发现,对应的数二进制位数一定比这个数长,自然1111对应的可能是10000、110000等等。

    于是,只需要从大到小进行一一匹配,就不会出现之前的情况。例如之前那种情况,如果11111先匹配,11111将会和0匹配,而1111将会在之前就和10000匹配了。

    ps:据说sum结果是n*(n+1),可以找规律找出来。不过我暂时推不出来。

    ps:结果可能很大,需要long long来存。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    using namespace std;
    
    int a[100005], Hash[100005], n;
    long long sum;
    
    void qt()
    {
        sum = 0;
        memset(Hash, -1, sizeof(Hash));
        int k, v, val, p;
        for (int i = n; i >= 0; i--)
        {
            if (Hash[i] >= 0)
                continue;
            k = i;
            p = 1;
            val = 0;
            for (;k;)
            {
                v = k & 1;
                val += (v^1) * p;
                p <<= 1;
                k >>= 1;
            }
            Hash[i] = val;
            Hash[val] = i;
        }
        for (int i = 0; i <= n; ++i)
            sum += a[i]^Hash[a[i]];
    }
    
    int main()
    {
        //freopen("test.txt", "r", stdin);
        while (scanf("%d", &n) != EOF)
        {
            for (int i = 0; i <= n; ++i)
                scanf("%d", &a[i]);
            qt();
            printf("%I64d
    ", sum);
            for (int i = 0; i <= n; ++i)
            {
                if (i)
                    printf(" ");
                printf("%d", Hash[a[i]]);
            }
            printf("
    ");
        }
        return 0;
    }
    

      

     
  • 相关阅读:
    UVA 10003:Cutting Sticks 区间DP
    UVAlive 10154:Dire Wolf 区间DP
    HDU 5071:Chat(2014 Asia AnShan Regional Contest)
    HDU 5074:Hatsune Miku(2014 Asia AnShan Regional Contest)
    android 代码混淆及问题大集锦
    android调试bug集锦 onActivityResult立即返回,并且被CANCEL
    开启g++ 编辑器 c++11特性
    解析最简单的验证码
    将图片文件转换为.py文件
    使用pyinstaller 2.1将python打包并添加版本信息和图标
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4067459.html
Copyright © 2011-2022 走看看