Codeforces Round #177 (Div. 2)---E. Polo the Penguin and XOR operation(贪心)

小企鹅Polo喜欢排列组合,特别是从0到n的整数排列。他定义了排列的美丽数为所有相邻元素异或操作的结果。问题求解在n的范围内,具有最大美丽数的排列。输入包含一个正整数n,输出最大美丽数及对应排列。解题策略是从小于等于n开始,找到每次异或后二进制位全为1的数对,构造排列。
摘要由CSDN通过智能技术生成

Little penguin Polo likes permutations. But most of all he likes permutations of integers from 0 to n, inclusive.

For permutation p = p0, p1, …, pn, Polo has defined its beauty — number .

Expression means applying the operation of bitwise excluding “OR” to numbers x and y. This operation exists in all modern programming languages, for example, in language C++ and Java it is represented as “^” and in Pascal — as “xor”.

Help him find among all permutations of integers from 0 to n the permutation with the maximum beauty.
Input

The single line contains a positive integer n (1 ≤ n ≤ 106).
Output

In the first line print integer m the maximum possible beauty. In the second line print any permutation of integers from 0 to n with the beauty equal to m.

If there are several suitable permutations, you are allowed to print any of them.
Sample test(s)
Input

4

Output

20
0 2 1 4 3

观察可以发现,两个数异或以后,如果二进制每一位都为1,那么一定最大,所以我们的策略是,枚举每一个 2i 1 ,当然是从大于等于n的那个开始,然后每次去找符合的满足 A+B=2i 1 的数

/*************************************************************************
    > File Name: CF-177-E.cpp
    > Author: ALex
    > Mail: zchao1995@gmail.com 
    > Created Time: 2015年04月08日 星期三 16时01分33秒
 ************************************************************************/

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#include <set>
#include <vector>

using namespace std;

const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

int per[1001000];

int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        int use1 = 0, use2 = 0;
        for (int i = 1; i <= n; ++i)
        {
            use1 ^= i;
        }
        LL ans = 0;
        int m = n;
        int high = 0;
        while (high < n)
        {
            high = 2 * high + 1; 
        }
        int use;
        while (high)
        {
            use = n;
            while (use > 0 && high - use <= n)
            {
                ans += high;
                per[use] = high - use;
                use2 ^= (high - use);
                --use;
            }
            high >>= 1;
            n = use;
        }
        per[0] = (use2 ^ use1);
        ans += per[0];
        printf("%I64d\n", ans);
        printf("%d", per[0]);
        for (int i = 1; i <= m; ++i)
        {
            printf(" %d", per[i]);
        }
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值