【CodeForces - 288C】Polo the Penguin and XOR operation (思维、异或运算)

版权声明:如果有什么问题,欢迎大家指出,希望能和大家一起讨论、共同进步。 https://blog.csdn.net/QQ_774682/article/details/84421910

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 xand 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.

Examples

Input

4

Output

20
0 2 1 4 3

题意:

给0~n,n+1个数让你找出一种排列,使得第i个位置上的数字与i做异或运算,然后所有运算结果加和,求使得加和最大排列。

思路:

首先,我们应该知道两个数做异或运算是相同为1,不同为0,即两个数都看成二进制,每一位都做运算,这一位上两个都是1或都是0,那么运算结果是0,否则为1。

如果想要最后的加和最大,那么尽量 就不要让两个数的二进制有重合的1,,因为如果有重合的1,那么异或完之后的结果一定会比两个数直接加和要小,如果没有冲突的1,那么两个数异或完后的结果应该等于两个数的加和。因此我们可以把二进制每一位都是1的数找出来,打个表。然后从后往前找,先找最后一个数n,从表中找到大于等于他的第一个数,然后两个数的差,就是最好的和n匹配的数,然后以这两个数为端点,同时向中间缩进,每一个数一定都是符合条件的最大的(可以自己写一下看看),接下来把最大的端点换成上次循环的起点的前一个数,重复循环,直到起点为0为止。

这道题目应该注意的是,最后的加和会很大所以应该开longlong,其次打表时,要注意范围,看看打的长度够不够。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<set>
#include<iostream>
#include<map>
#include<stack>
#include<cmath>
#include<algorithm>
#define ll long long
#define mod 1000000007
#define eps 1e-8
using namespace std;
int num[1010101];
int main()
{
	int n,k;
	ll sum=0;//加和很大记得开longlong 
	scanf("%d",&n);
	int one[100]={0};
	one[1]=1;
	for(int i=2;i<=24;i++)
	{
		one[i]=(one[i-1]<<1)+1;//打表后,要看看是不是比给的范围大,不要打小了 
	}
	int ne=n;
	while(1)
	{
		int tt=*lower_bound(one,one+23,ne);
		int ff=tt-ne;
		for(int st=tt-ne,ed=ne;st<ed;ed--,st++)
		{
			sum+=(st^ed)*2;
			num[st]=ed;
			num[ed]=st;
		}
		ne=tt-ne-1;
		if(ff==0||ne<0)
		break;
	} 
	printf("%lld\n",sum);
	printf("%d",num[0]);
	for(int i=1;i<=n;i++)
	{
		printf(" %d",num[i]);
	}
	putchar('\n');
	
}

猜你喜欢

转载自blog.csdn.net/QQ_774682/article/details/84421910