题目:https://codeforces.com/contest/1174/problem/D

D. Ehab and the Expected XOR Problem

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Given two integers n and x, construct an array that satisfies the following conditions:

  • for any element ai in the array, 1≤ai<2n;
  • there is no non-empty subsegment with bitwise XOR equal to 0 or x,
  • its length l should be maximized.

A sequence b is a subsegment of a sequence a if b can be obtained from a by deletion of several (possibly, zero or all) elements from the beginning and several (possibly, zero or all) elements from the end.

Input

The only line contains two integers n and x (1≤n≤18, 1≤x<218).

Output

The first line should contain the length of the array l.

If l is positive, the second line should contain l space-separated integers a1, a2, …, al (1≤ai<2n) — the elements of the array a.

If there are multiple solutions, print any of them.

Examples

input

Copy

3 5

output

Copy

3
6 1 3

input

Copy

2 4

output

Copy

3
1 3 1 

input

Copy

1 1

output

Copy

0

Note

In the first example, the bitwise XOR of the subsegments are {6,7,4,1,2,3}.

 

题意:给你两个数字n和x,构造一个数组使得他们的任意子段异或和不等于0和x,对于每个数a[i],有1<=a[i]<2^n,要求构造的这              个数组尽可能的长。

当时比赛的时候看到这个题目完全就找不到方向,不知道该往哪一个方向去思考。后来看了题解,觉得这个解题思路很有趣,于是打算写一篇博客留着以后看看。

 

思路:考虑构造这个数组本身的话,感觉是力不从心,不知如何下手。换个想法,1---2^n之间的数异或和肯定也是在这个范围之            内,那我们就构造这个数组的异或前缀和,因为任意子段异或和不能等于0,所以我们构造的这个异或前缀数组里面就不能有两个相同的数,如果x>=2^n,显然我们可以取1--2^n之间的所有数,也就是2^n-1个;如果x是在1--2^n这个范围内的话,假如我们选取一个数k的话,那么k^x肯定就不能选了,因为如果选了的话就会导致异或和会出现x,不合法。 于是我们从1--n依次选一个数作为前缀和,同时标记一下k^x,下次再遇上的话就不再选。把前缀异或和数组构造出来之后,相邻两个数再异或一下即可构造出符合要求的答案。具体参看代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1000 * 1000 + 10;
int a[maxn], b[maxn];
int n, x;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	memset(b,0,sizeof(b));
	cin >> n >> x;

	b[x] = 1;               //构造的数组肯定不能有x,很显然的
	int cnt = 1;
	for (int i = 1; i < (1 << n); i++) {
		if (b[i])continue;				//如果这个数已经被标记过了,就不选
		b[i] = 1; b[i^x] = 1;   //选择i之后,那么i^x啃的就不能选了,标记一下,下次就可以不用选了
		a[cnt++] = i;    //记录选的这个数
	}

	cout << cnt - 1 << endl;
	for (int i = 1; i < cnt; i++)cout << (a[i] ^ a[i - 1]) << ' ';   //根据前缀和的构造,a[i]^a[i-1]就是第i个数

	cout << endl;

	return 0;
}