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>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 40005

struct GROUP{
	vector<int> nodes;
};

GROUP group[NUM]; //強連結成分のグループ
vector<int> G[NUM];
vector<int> reverse_G[NUM];
stack<int> S;

bool check[NUM];
int N,X,A,O;
int POW[16];
int table[NUM],in_num[NUM];
double sleep[NUM];

int group_index;

void dfs(int node_id){
	check[node_id] = true;

	for(int i = 0; i < G[node_id].size(); i++){
		if(!check[G[node_id][i]])dfs(G[node_id][i]);
	}
	S.push(node_id);
}

void reverse_dfs(int node_id){
	check[node_id] = true;

	group[group_index].nodes.push_back(node_id); //group[group_index]にノードを突っ込む
	table[node_id] = group_index;

	for(int i = 0; i < reverse_G[node_id].size(); i++){
		if(!check[reverse_G[node_id][i]])reverse_dfs(reverse_G[node_id][i]);
	}
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= 15; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d %d %d",&N,&X,&A,&O);
	if(X == 0){

		printf("No\n");
		return 0;
	}

	for(int i = 0; i < POW[N+1]; i++){
		for(int k = 0; k < POW[N+1]; k++){
			if(((i^k) == X) || ((i&k) == A) || ((i|k) == O)){ //true,falseを別にするペア

				G[i].push_back(k^X);
				reverse_G[k^X].push_back(i);
			}
		}
	}

	for(int i = 0; i < POW[N+1]; i++)check[i] = false;

	//まずは帰りがけ順を計算
	for(int i = 0; i < POW[N+1];i++){
		if(!check[i])dfs(i);
	}

	for(int i = 0; i < POW[N+1];i++)check[i] = false;

	group_index = -1;
	//ノードを、帰りがけ順の逆順に、各強連結成分(グループ)に分解
	while(!S.empty()){
		if(!check[S.top()]){
			group_index++;

			reverse_dfs(S.top());
		}
		S.pop();
	}

	for(int i = 0; i < POW[N+1]; i++){
		if(i < (i^X) && table[i] == table[i^X]){
			printf("No\n");
			return 0;
		}
	}

	vector<int> ANS;
	for(int i = 0; i < POW[N+1]; i++){
		if(i > (i^X))continue;

		if(table[i] > table[i^X]){

			ANS.push_back(i);
		}else{

			ANS.push_back(i^X);
		}
	}

	printf("Yes\n");
	printf("%d",ANS[0]);

	for(int i = 1; i < ANS.size(); i++){

		printf(" %d",ANS[i]);
	}
	printf("\n");

	return 0;
}

