D: XORANDORBAN

Problem Statement

You are given a positive integer N. Your task is to determine a set S of 2^N integers satisfying the following conditions:

* All the integers in S are at least 0  and less than 2^{N+1}.
* All the integers in S are distinct.
* You are also given three integers X, A, and O, where 0 \leq X, A, O < 2^{N+1}. Then, any two integers (a, b) in S must satisfy a {\it xor} b \neq X, a {\it and} b \neq A, a {\it or} b \neq O, where {\it xor}, {\it and}, {\it or} are bitwise xor, bitwise and, bitwise or, respectively. Note that a and b are not necessarily different.



Input


N X A O

Constraints

* 1 \leq N \leq 13
* 0 \leq X, A, O < 2^{N+1}
* Inputs consist only of integers.



Output

If there is no set satisfying the conditions mentioned in the problem statement, output `No` in a line. Otherwise, output `Yes` in the first line, and then output 2^N integers in such a set in the second line. If there are multiple sets satisfying the conditions, you can output any of them.

Sample Input 1


2 6 1 5

Output for Sample Input 1


Yes
0 3 4 7


Sample Input 2


3 0 5 1

Output for Sample Input 2


No

Sample Input 3


3 4 2 5

Output for Sample Input 3


Yes
1 0 6 15 8 9 14 7






Example

Input

2 6 1 5


Output

Yes
0 3 4 7
#include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0; i<(n); i++)

#define DEBUG(x) cerr << #x << ": " << (x) << endl;

int n,x,a,o;
int m;

struct SCC{
	int n;
	vector<vector<int>> G,rG;
	vector<int> vs, cmp;
	vector<bool> used;

	SCC(int n):n(n),G(n),rG(n),cmp(n){}

	void add_edge(int from, int to){
		G[from].push_back(to);
		rG[to].push_back(from);
	}
	void dfs(int v){
		used[v] = true;
		for(int to : G[v]){
			if(!used[to])dfs(to);
		}
		vs.push_back(v);
	}
	void rdfs(int v, int k){
		used[v] = true;
		cmp[v] = k;
		for(int to : rG[v]){
			if(!used[to])rdfs(to,k);
		}
	}
	int solve(){
		used.assign(n,false);
		vs.clear();
		for(int i=0; i<n; i++){
			if(!used[i])dfs(i);
		}
		used.assign(n, false);
		int k = 0;
		for(int i=(int)vs.size()-1; i>=0; i--){
			if(!used[vs[i]])rdfs(vs[i],k++);
		}
		return k;
	}
	int operator[](int k) const{
		return cmp[k];
	}
};

struct TwoSAT {
	int n;
	SCC scc;
	vector<bool> ans;
	TwoSAT(int n):n(n),scc(n*2),ans(n){}
	void add(int a, int b){
		a = a > 0 ? a-1 : (n-a-1);
		b = b>0 ? b-1 : (n-b-1);
		scc.add_edge((a+n)%(2*n), b);
		scc.add_edge((b+n)%(2*n), a);
	}
	void addng(int a, int b){
		add(-(a+1), -(b+1));
	}
	bool solve(){
		scc.solve();
		for(int i=0; i<n; i++){
			if(scc.cmp[i] == scc.cmp[n+i])return false;
		}
		for(int i=0; i<n; i++){
			ans[i] = scc.cmp[i] > scc.cmp[n+i];
		}
		return true;
	}
};

int main(){
	cin>>n>>x>>a>>o;
	m = 1<<(n+1);
	if(x==0){
		// ng
		puts("No");
		return 0;
	}
	TwoSAT twosat(m);
	int msk = (1<<(n+1))-1;
	REP(i,1<<(n+1)){
		int op = x ^ i;
		twosat.addng(i,op);
		twosat.add(i+1, op+1);
	}
	// and
	REP(i,1<<(n+1)){
		if((i&a)!=a)continue;
		int po = msk ^ i;
		int op = po;
		while(true){
			twosat.addng(i,(i&a) ^ op);
			if(op==0)break;
			op = (op - 1) & po;
		}
	}
	// or
	REP(i,1<<(n+1)){
		if((i|o)!=o)continue;
		int po = i;
		int op = po;
		while(true){
			twosat.addng(i,((~i)&o) ^ op);
			if(op==0)break;
			op = (op - 1) & po;
		}
	}
	if(!twosat.solve()){
		puts("No");
		return 0;
	}
	puts("Yes");
	vector<int> ans;
	REP(i,m)if(twosat.ans[i]){
		ans.push_back(i);
	}
	REP(i,m/2){
		printf("%d%c",ans[i]," \n"[i==m/2-1]);
	}

	// REP(i,1<<(n+1)){
	// 	int op = x ^ i;
	// 	if(twosat.ans[i] && twosat.ans[op]){
	// 		puts("NG");
	// 		DEBUG(i); DEBUG(op);
	// 		return 1;
	// 	}
	// 	twosat.addng(i,op);
	// }
	// // and
	// REP(i,1<<(n+1)){
	// 	if((i&a)!=a)continue;
	// 	int po = msk ^ i;
	// 	int op = po;
	// 	while(true){
	// 		if(twosat.ans[i] && twosat.ans[(i&a) ^ op]){
	// 			puts("NG - and");
	// 			DEBUG(i); DEBUG(((i&a) ^ op));
	// 			return 1;
	// 		}
	// 		twosat.addng(i,(i&a) ^ op);
	// 		if(op==0)break;
	// 		op = (op - 1) & po;
	// 	}
	// }
	// // or
	// REP(i,1<<(n+1)){
	// 	if((i|o)!=o)continue;
	// 	int po = i;
	// 	int op = po;
	// 	while(true){
	// 		if(twosat.ans[i] && twosat.ans[((~i)&o) ^ op]){
	// 			puts("NG - or");
	// 			DEBUG(i); DEBUG((((~i)&o) ^ op));
	// 			return 1;
	// 		}
	// 		twosat.addng(i,((~i)&o) ^ op);
	// 		if(op==0)break;
	// 		op = (op - 1) & po;
	// 	}
	// }
	return 0;
}

