1. 程式人生 > >【CodeForces - 288C】Polo the Penguin and XOR operation (思維、異或運算)

【CodeForces - 288C】Polo the Penguin and XOR operation (思維、異或運算)

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.

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');
	
}