hdu 5014 Number Sequence 找规律 | 贪心 2014 ACM/ICPC Asia Regional Xi'an Online

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014

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

Source


线下 AC的,比赛的时候其实已经找到规律了,然后自己二呵呵的把binary数组初值赋错了,一直没发现....粗糙党

不过后来看正解是贪心...但我们的规律也是按贪心找的...

思路:

     如果两个数的二进制位数不同,这两个数的异或值就会越大,所以尽量使   a^b == 2^x - 1,这样我们得到了一个基本关系。

  

a:   0  1  2  3  4   5  6  7  8  9  10 11  12  13  14  15  16 17 ...
b:   0  2  1  4  3  10  9  8  7  6  5  20  19  18  17  16  15 14 ...

可以看出从17~11是递增,10~5也是递增的,4~3是递增的,2~1递增,如果a是上限,那么直接找2^x - 1 >= a,这里=a ,只有第一次累加的时候,然后一次往回加,加到小于上一次的最小值....重复这个过程...我用了low和high来完成累加的过程,并标记每一次的上下限

代码:

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cctype>
#include <cmath>
#include <stack>
#include <queue>
#include <list>
#include <map>
#include <set>

using namespace std;

#define min2(x, y)     min(x, y)
#define max2(x, y)     max(x, y)
#define min3(x, y, z)  min(x, min(y, z))
#define max3(x, y, z)  max3(x, max(y, z))
#define clr(x, y)      memset(x, y, sizeof(x))
#define fr(i,n)        for(int i = 0; i < n; i++)
#define fr1(i,n)       for(int i = 1; i < n; i++)
#define upfr(i,j,n)    for(int i = j; i <= n; i++)
#define dowfr(i,j,n)   for(int i = n; i >= j; i--)
#define scf(n)         scanf("%d", &n)
#define ptf(n)         printf("%d",n)
#define ptfl(n)        printf("%I64d",n)
#define ptfs(s)        printf("%s",s)
#define ptk()          printf(" ")
#define ptln()         printf("\n")
#define srt(a,n)       sort(a,n)
#define LL long long
#define pi acos(-1.0)
#define inf 1 << 31-1
#define eps 0.00001
#define maxn 100005
int arr[maxn];
int ans[maxn];
int binary[maxn];
int vis[maxn];
int main()
{
    //freopen("in.txt","r",stdin);
    binary[0] = 1;    //2的0次是1,开始自己写成2了,2333
    fr1(i,20)
    binary[i] = binary[i-1] * 2;
    int n;
    while(scf(n) !=EOF )
    {
        clr(vis,0);
        clr(ans,0);
        clr(arr,0);
        fr(i,n+1)
        scf(arr[i]);
        int tmp;
        fr(i,20)
        {
            if(binary[i] > n)
                {
                    tmp = binary[i];
                    break;
                }
        }
        //ptf(tmp);
        int low,high;
        low = tmp - 1 - n;
        ans[n] = low;
        high = n;
        dowfr(i,0,n-1)
        {

            if(ans[i+1]+1 == n)
                ans[i] = n;
            else if(ans[i+1] + 1 < high)
                ans[i] = ans[i+1] + 1;
            else
            {
                fr(j,20)
                {
                    if(binary[j] > i)
                    {
                        high = low ;
                        low = binary[j] - 1 - i;
                        break;
                    }
                }
                ans[i] = low;
            }
        }
        __int64 sum = 0;
        fr(i,n+1)
        sum += i ^ ans[i];
        ptfl(sum);
        ptln();
        ptf(ans[arr[0]]);
        upfr(i,1,n)
           ptk(),ptf(ans[arr[i]]);
        ptln();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值