Problem:
Score : 800 points

Problem Statement

You are given integers N,\ A and B.
Determine if there exists a permutation (P_0,\ P_1,\ ...\ P_{2^N-1}) of (0,\ 1,\ ...\ 2^N-1) that satisfies all of the following conditions, and create one such permutation if it exists.

P_0=A

P_{2^N-1}=B

For all 0 \leq i < 2^N-1, the binary representations of P_i and P_{i+1} differ by exactly one bit.

Constraints

1 \leq N \leq 17

0 \leq A \leq 2^N-1

0 \leq B \leq 2^N-1

A \neq B

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N A B

Output

If there is no permutation that satisfies the conditions, print NO.

If there is such a permutation, print YES in the first line.
Then, print (P_0,\ P_1,\ ...\ P_{2^N-1}) in the second line, with spaces in between.
If there are multiple solutions, any of them is accepted.

Sample Input 1

2 1 3

Sample Output 1

YES
1 0 2 3

The binary representation of P=(1,0,2,3) is (01,00,10,11), where any two adjacent elements differ by exactly one bit.

Sample Input 2

3 2 1

Sample Output 2

NO

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <set>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstring>
#include <cmath>
#include <string>
#include <bitset>

#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,avx,avx2")

#include <cstring>
#include <unordered_map>
#include <map>
#include <algorithm>
#include <cstdio>
#include <set>
#include <vector>
#include <unordered_set>
#include <cassert>
#include <string>
#include <cmath>
#include <set>
#include <bitset>

namespace olymplib {
	namespace {
		template <class T> void writeInt(T x);
		template <class T> void writeUInt(T x);
		void writeChar(int x);
		void writeWord(const char *s);
		void writeDouble(double x, int len = 0);
		static const int buf_size = 4096;
		static int write_pos = 0;
		static char write_buf[buf_size];
		static char buf[buf_size];
		static int buf_len = 0, buf_pos = 0;
		//-- read
		template <class T = int> T readInt();
		double readDouble();
		int readUInt();
		int readChar();
		void readWord(char *s);
		bool readLine(char *s); // do not save '\n'
		bool isEof();
		int peekChar();
		bool seekEof();
		void flush();
		//--------------------------
		bool isEof() {
			if (buf_pos == buf_len) {
				buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
				if (buf_pos == buf_len)
					return 1;
			}
			return 0;
		}

		int getChar() {
			return isEof() ? -1 : buf[buf_pos++];
		}

		int peekChar() {
			return isEof() ? -1 : buf[buf_pos];
		}

		bool seekEof() {
			int c;
			while ((c = peekChar()) != -1 && c <= 32)
				buf_pos++;
			return c == -1;
		}

		int readChar() {
			int c = getChar();
			while (c != -1 && c <= 32)
				c = getChar();
			return c;
		}

		int readUInt() {
			int c = readChar(), x = 0;
			while ('0' <= c && c <= '9')
				x = x * 10 + c - '0', c = getChar();
			return x;
		}

		template <class T>
		T readInt() {
			int s = 1, c = readChar();
			T x = 0;
			if (c == '-')
				s = -1, c = getChar();
			while ('0' <= c && c <= '9')
				x = x * 10 + c - '0', c = getChar();
			return s == 1 ? x : -x;
		}

		template <class Double = double>
		double readDouble() {
			int s = 1, c = readChar();
			Double x = 0;
			if (c == '-')
				s = -1, c = getChar();
			while ('0' <= c && c <= '9')
				x = x * 10 + c - '0', c = getChar();
			if (c == '.') {
				c = getChar();
				double coef = 1;
				while ('0' <= c && c <= '9')
					x += (c - '0') * (coef *= 1e-1), c = getChar();
			}
			return s == 1 ? x : -x;
		}

		void readWord(char *s) {
			int c = readChar();
			while (c > 32)
				*s++ = c, c = getChar();
			*s = 0;
		}

		bool readLine(char *s) {
			int c = getChar();
			while (c != '\n' && c != -1)
				*s++ = c, c = getChar();
			*s = 0;
			return c != -1;
		}

		//only supports fixed precision for now (hence huge values are not allowed)
		void writeDouble(double x, int output_len) {
			if (x < 0)
				writeChar('-'), x = -x;
			int t = (int)x;
			writeUInt(t), x -= t;
			writeChar('.');
			for (int i = output_len - 1; i > 0; i--) {
				x *= 10;
				t = 9 < (int)x ? 9 : x;
				writeChar('0' + t), x -= t;
			}
			x *= 10;
			t = 9 < (int)(x + 0.5) ? 9 : (int)(x + 0.5);
			writeChar('0' + t);
		}

		void writeChar(int x) {
			if (write_pos == buf_size)
				fwrite(write_buf, 1, buf_size, stdout), write_pos = 0;
			write_buf[write_pos++] = x;
		}

		template <class T>
		void writeUInt(T x) {
			char s[24];
			int n = 0;
			while (x || !n)
				s[n++] = '0' + x % 10, x /= 10;
			while (n--)
				writeChar(s[n]);
		}

		template<>
		void writeInt<int>(int x) {
			if (x < 0)
				writeChar('-'), x = -x;

			char s[10];
			int n = 0;
			while (x || !n)
				s[n++] = '0' + x % 10, x /= 10;
			while (n--)
				writeChar(s[n]);
		}

		template <class T>
		void writeInt(T x) {
			if (x < 0)
				writeChar('-'), x = -x;

			char s[24];
			int n = 0;
			while (x || !n)
				s[n++] = '0' + x % 10, x /= 10;
			while (n--)
				writeChar(s[n]);
		}

		void writeWord(const char *s) {
			while (*s)
				writeChar(*s++);
		}

		void flush() {
			if (write_pos) {
				fwrite(write_buf, 1, write_pos, stdout), write_pos = 0;
			}
		}
	}

	class TOutputStream {
		int precision_;
	public:
		void precision(int new_prec) {
			precision_ = new_prec;
		}

		TOutputStream& operator<< (bool arg) {
			writeChar('0' + arg);
			return *this;
		}

		TOutputStream& operator<< (char arg) {
			writeChar(arg);
			return *this;
		}

		TOutputStream& operator<< (const char* arg) {
			writeWord(arg);
			return *this;
		}

		TOutputStream& operator << (float arg) {
			writeDouble(arg, precision_);
			return *this;
		}

		TOutputStream& operator << (double arg) {
			writeDouble(arg, precision_);
			return *this;
		}

		TOutputStream& operator << (long double arg) {
			writeDouble(arg, precision_);
			return *this;
		}

		TOutputStream& operator<< (int arg) {
			writeInt(arg);
			return *this;
		}

		TOutputStream& operator<< (long long arg) {
			writeInt(arg);
			return *this;
		}

		TOutputStream& operator<< (const std::string& arg) {
			writeWord(arg.c_str());
			return *this;
		}

		void flush() {
			olymplib::flush();
		}

		typedef TOutputStream& (*MyStreamManipulator)(TOutputStream&);

		TOutputStream& operator<<(const MyStreamManipulator& manip) {
			return manip(*this);
		}

		~TOutputStream() {
			flush();
		}
	};

	class TInputStream {
	public:
		TInputStream& operator>> (bool& arg) {
			arg = readChar() - '0';
			return *this;
		}

		TInputStream& operator>> (char& arg) {
			arg = readChar();
			return *this;
		}

		//please know what you're doing.
		TInputStream& operator>> (char*& arg) {
			readWord(arg);
			return *this;
		}

		TInputStream& operator >> (float& arg) {
			arg = readDouble<float>();
			return *this;
		}

		TInputStream& operator >> (double& arg) {
			arg = readDouble<double>();
			return *this;
		}

		TInputStream& operator >> (long double& arg) {
			arg = readDouble<long double>();
			return *this;
		}

		TInputStream& operator>> (int& arg) {
			arg = readInt<int>();
			return *this;
		}

		TInputStream& operator>> (long long& arg) {
			arg = readInt<long long>();
			return *this;
		}

		TInputStream& operator>> (std::string& arg) {
			arg.clear();
			arg.reserve(16);
			arg.push_back(readChar());
			while (char c = peekChar()) {
				if (c == -1 || c <= 32)
					break;
				arg.push_back(getChar());
			}
			arg.shrink_to_fit();
			return *this;
		}
	};

	static TInputStream cin;
	static TOutputStream cout;

	static TOutputStream& endl(TOutputStream& stream) {
		stream << '\n';
		stream.flush();
		return stream;
	}
}

using namespace olymplib;
using namespace std;

const int N = 2e5 + 10;
const int MOD = 1e9 + 7;

int popcnt(int x) {
	if (x == 0) return 0;
	return 1 + popcnt(x & (x - 1));
}

vector <int> build_gray(int n) {
	if (n == 0) {
		return { 0 };
	}
	if (n == 1) {
		return { 0, 1 };
	}
	auto v = build_gray(n - 1);
	vector <int> res = v;
	reverse(v.begin(), v.end());
	for (auto& x : v) {
		x ^= (1 << (n - 1));
		res.push_back(x);
	}
	return res;
}

vector <int> solve(int n, int a, int b) {
	if (popcnt(a ^ b) % 2 == 0) {
		return {};
	}
	vector <int> eqbit;
	vector <int> neqbit;
	int start = 0;
	for (int i = 0; i < n; ++i) {
		if ((a & (1 << i)) == (b & (1 << i))) {
			eqbit.push_back(i);
			start ^= (a & (1 << i));
		} else {
			neqbit.push_back(i);
		}
	}
	vector <int> vv = build_gray(eqbit.size());
	for (auto& x : vv) {
		int l = 0;
		for (int i = 0; i < eqbit.size(); ++i) {
			if (x & (1 << i)) {
				l ^= (1 << eqbit[i]);
			}
		}
		x = l;
	}
	vector <int> res;
	for (int id = 0; id < vv.size(); ++id) {
		if (vv[id] == start) {
			for (int x = id; x < vv.size(); ++x) {
				res.push_back(vv[x]);
			}
			for (int x = 0; x < id; ++x) {
				res.push_back(vv[x]);
			}
		}
	}
	for (int i = 0; i < neqbit.size(); ++i) {
		vector <int> newres;
		if (b & (1 << neqbit[i])) {
			for (auto x : res) {
				newres.push_back(x);
			}
			reverse(res.begin(), res.end());
			for (auto& x : res) {
				x ^= (1 << neqbit[i]);
				newres.push_back(x);
			}
		} else {
			for (auto& x : res) {
				x ^= (1 << neqbit[i]);
				newres.push_back(x);
			}
			reverse(res.begin(), res.end());
			for (auto& x : res) {
				x ^= (1 << neqbit[i]);
				newres.push_back(x);
			}

		}
		res.swap(newres);
	}
	return res;
}

int main() {
	int n, a, b;
	cin >> n >> a >> b;
	auto res = solve(n, a, b);
	if (res.size() != 0) {
		if (res[0] != a || res.back() != b) {
			cout << "NO" << endl;
			return 0;
		}
		cout << "YES\n";
		assert(res[0] == a && res.back() == b);
		for (auto x : res) {
			cout << x << " ";
		}
		cout << endl;
	} else {
		cout << "NO" << endl;
	}
	return 0;
}