#include <stdio.h>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <list>
#include <iterator>
#pragma warning(disable:4996)
 
typedef long long ll;
#define MIN(a, b) ((a)>(b)? (b): (a))
#define MAX(a, b) ((a)<(b)? (b): (a))
#define LINF 9223300000000000000
#define INF 2140000000
#define MOD 1000000007
using namespace std;


bool solve( long n, long a, long b, long* ans );


// (0,..,2^n-1)について、最初が0で最後がaとなるように並び替えたものを作成し、ans(長さ2^nの配列)にoutput する。
// ただし、nは1以上、aは1以上(2^n-1)以下とする。
// 作成した場合はtrue、作成できない場合はfalseを返す。
bool solve0( long n, long a, long* ans )
{
    // aが0のときはエラー
    if(a==0) { printf("internal error\n"); return false; }

    if(n==1) {
        ans[0]=0; ans[1]=1;
    }
    else {
        // a は0でないので、どこかのbitが立っているはず。それを見つけて i とする
        long i;
        for(i=0; i<n; i++) {
            if(a & (1<<i)) break;
        }
        if(i==n) { printf("internal error\n"); return false; }

        // i と異なる j をとって、以下のように配列の前半と後半を作成する。
        // 前半：(0,..,2^n-1) のうち、桁 i のbitが立っていないもののみ並びかえる。ただし最初を0、最後を (1<<j)（つまり桁jのbitだけ立てたもの）とする
        // 後半：(0,..,2^n-1) のうち、桁 i のbitが立っているもののみ並びかえる。ただし最初を (1<<i)+(1<<j)（つまり桁iと桁jのbitだけ立てたもの）として最後をaにする
        long j=(i==0? 1: 0);
        if(a==(1<<i)+(1<<j)) {
            // 偶奇を考えると構成不可能なパターンなのでfalseを返す
            return false;
        }

        // 前半の配列を構成するために、桁iを除いて考えて1桁少ない問題を解く
        long j_mod = (j>i? j-1: j);
        if( !solve0( n-1, (1<<j_mod), ans ) ) {
            return false;
        }

        // 後半の配列を構成ために、桁iを除いて考えて1桁少ない問題を解く
        long a_mod = a;
        {
            long m;
            for(m=i; m<n-1; m++) {
                if (a_mod & (1<<(m+1)) ) {
                    a_mod |= (1<<m);
                }
                else {
                    a_mod &= ~(1<<m);
                }
            }
            a_mod &= ~(1<<(n-1));
        }

        if( !solve( n-1, (1<<j_mod), a_mod, ans+(1<<(n-1)) ) ){
            return false;
        }

        // 前半の配列を補正（桁を1つ少ない問題を解いたので本来の形に修正）
        long m;
        for(m=0; m<(1<<(n-1)); m++) {
            long k;
            for(k=n-1; k>i; k--) {
                if( ans[m] & (1<<(k-1)) ) {
                    ans[m] |= (1<<k);
                }
                else {
                    ans[m] &= ~(1<<k);
                }
            }
            ans[m] &= ~(1<<i);
        }

        // 後半の配列を補正（桁を1つ少ない問題を解いたので本来の形に修正）
        for(m=(1<<(n-1)); m<(1<<n); m++) {
            long k;
            for(k=n-1; k>i; k--) {
                if( (ans[m] & (1<<(k-1))) ) {
                    ans[m] |= (1<<k);
                }
                else {
                    ans[m] &= ~(1<<k);
                }
            }
            ans[m] |= (1<<i);
        }        
    }
    return true;
}


// (0,..,2^n-1)について、最初がaで最後がbとなるように並び替えたものを作成し、ans(長さ2^nの配列)にoutput する。
// ただし、nは1以上、a,bは0以上(2^n-1)以下で、a≠bとする。
// 作成した場合はtrue、作成できない場合はfalseを返す。
bool solve( long n, long a, long b, long* ans )
{
    // 最初が0で最後が(a^b)になるようなものを作成して、後で全ての要素について ^a すればよい。
    if( !solve0( n, a^b, ans ) ) {
        return false;
    }

    // modify
    long i;
    for(i=0; i<(1<<n); i++) {
        ans[i] ^= a;
    }
    return true;
}


int main(int argc, char* argv[])
{
    long n, a, b;
    scanf("%ld%ld%ld", &n, &a, &b);

    vector<long> ans(1<<n);
    bool bOk = solve( n, a, b, &(ans[0]) );
    if( bOk ) {
        printf("YES\n");
        long i;
        for(i=0; i<(1<<n); i++) {
            printf("%ld ", ans[i]);
        }
        printf("\n");
    }
    else {
        printf("NO\n");
    }

    return 0;
}


Measured memory_bytes: 2048