Problem p03097 (C++)

Buggy submission (status: Runtime Error):
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <complex>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cassert>
#include <functional>

typedef long long ll;
using namespace std;

#ifndef LOCAL
#define debug(x) ;
#else
#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;

template <typename T1, typename T2>
ostream &operator<<(ostream &out, const pair<T1, T2> &p) {
  out << "{" << p.first << ", " << p.second << "}";
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << '{';
  for (const T &item : v)
    out << item << ", ";
  out << "\b\b}";
  return out;
}
#endif

#define mod 1000000007              // 1e9+7(prime number)
#define INF 1000000000              // 1e9
#define LLINF 2000000000000000000LL // 2e18
#define SIZE 200010

int n;
int conv[20];

int ff(int x) {
  int r[20], res = 0;

  for (int i = 0; i < n; i++)
    r[conv[i]] = x & (1 << i);

  for (int i = 0; i < n; i++)
    res += (1 << i) * !!(r[i]);

  // cerr << x << " -> " << res << endl;
  return res;
}

int main() {
  int a, b;

  cin >> n >> a >> b;

  if (__builtin_popcount(a ^ b) % 2 == 0) {
    cout << "NO" << endl;
    return 0;
  }

  int pp = __builtin_popcount(a ^ b);

  puts("YES");

  if (n == 1) {
    printf("%d %d\n", a, b);
    return 0;
  }

  vector<int> vec[5];

  vec[0].push_back(0);
  vec[0].push_back(1);

  for (int i = 0; i < 4; i++) {
    for (int p = 0; p < vec[i].size(); p++) {
      for (int q = 0; q < vec[i].size(); q++) {
        int r;
        if (p % 2 == 0)
          r = q;
        else
          r = vec[i].size() - q - 1;

        vec[i + 1].push_back((vec[i][p] << (1 << i)) + vec[i][r]);
      }
    }
  }

  n--;

  vector<int> vec1;

  for (int i = 0; i < 5; i++) {
    if (n & (1 << i)) {
      if (vec1.size() == 0) {
        vec1 = vec[i];
        continue;
      }

      vector<int> vec2;

      for (int p = 0; p < vec[i].size(); p++) {
        for (int q = 0; q < vec1.size(); q++) {
          int r;
          if (p % 2 == 0)
            r = q;
          else
            r = vec1.size() - q - 1;

          vec2.push_back((vec1[r] << (1 << i)) + vec[i][p]);
        }
      }

      vec1 = vec2;
    }
  }

  int y = -1, x = -1;

  for (int i = 0; i < n; i++) {
    int q;
    if (i % 2 == 0) {
      q = __builtin_popcount(vec1[0] ^ vec1[i]) + 1;
    } else {
      q = __builtin_popcount(vec1[0] ^ vec1[i]);
    }

    if (q == pp) {
      y = i % 2 == 0;
      x = i;
      break;
    }
  }

  assert(y != -1);

  vector<int> vec2;

  for (int i = 0; i < x; i++) {
    if (i % 2 == 0)
      vec2.push_back(vec1[i] * 2 + 0);
    vec2.push_back(vec1[i] * 2 + 1);
    if (i % 2 == 1)
      vec2.push_back(vec1[i] * 2 + 0);
  }

  for (int i = x; i < vec1.size(); i++) {
    if (y == 0)
      vec2.push_back(vec1[i] * 2 + 1);
    if (y == 1)
      vec2.push_back(vec1[i] * 2 + 0);
  }

  for (int i = vec1.size() - 1; i >= x; i--) {
    if (y == 0)
      vec2.push_back(vec1[i] * 2 + 0);
    if (y == 1)
      vec2.push_back(vec1[i] * 2 + 1);
  }

  n++;

  set<int> t1, t2;

  for (int i = 0; i < n; i++) {
    int m = vec2.size();
    int p = vec2[0] & (1 << i);
    int q = vec2[m - 1] & (1 << i);

    int r = a & (1 << i);
    int s = b & (1 << i);

    if (p != q)
      t1.insert(i);
    if (r != s)
      t2.insert(i);
  }

  int cur = 0;
  for (int i = 0; i < n; i++) {
    if (t1.find(i) != t1.end())
      continue;
    while (t2.find(cur) != t2.end())
      cur++;

    conv[i] = cur++;
  }

  auto it1 = t1.begin();
  auto it2 = t2.begin();

  while (it1 != t1.end()) {
    conv[*it1] = *it2;
    it1++;
    it2++;
  }

  bool f[20];

  int tmp = ff(vec2[0]);

  for (int i = 0; i < n; i++) {
    int p = tmp & (1 << i);
    int q = a & (1 << i);

    f[i] = p ^ q;
  }

  int prev = -1;

  debug(vec2.size());

  for (int i = 0; i < vec2.size(); i++) {
    int res = ff(vec2[i]);

    for (int j = 0; j < n; j++) {
      if (f[j])
        res ^= 1 << j;
    }

    printf("%d ", res);

    assert(prev == -1 || __builtin_popcount(res ^ prev) == 1);
    prev = res;

    if (i == 0)
      assert(a == res);
  }
  assert(b == prev);

  puts("");

  sort(vec1.begin(), vec1.end());

  for (int i = 0; i < n; i++) {
    assert(vec1[i] == i);
  }

  return 0;
}


Fixed submission:
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <complex>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cassert>
#include <functional>

typedef long long ll;
using namespace std;

#ifndef LOCAL
#define debug(x) ;
#else
#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;

template <typename T1, typename T2>
ostream &operator<<(ostream &out, const pair<T1, T2> &p) {
  out << "{" << p.first << ", " << p.second << "}";
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << '{';
  for (const T &item : v)
    out << item << ", ";
  out << "\b\b}";
  return out;
}
#endif

#define mod 1000000007              // 1e9+7(prime number)
#define INF 1000000000              // 1e9
#define LLINF 2000000000000000000LL // 2e18
#define SIZE 200010

int n;
int conv[20];

int ff(int x) {
  int r[20], res = 0;

  for (int i = 0; i < n; i++)
    r[conv[i]] = x & (1 << i);

  for (int i = 0; i < n; i++)
    res += (1 << i) * !!(r[i]);

  // cerr << x << " -> " << res << endl;
  return res;
}

int main() {
  int a, b;

  cin >> n >> a >> b;

  if (__builtin_popcount(a ^ b) % 2 == 0) {
    cout << "NO" << endl;
    return 0;
  }

  int pp = __builtin_popcount(a ^ b);

  puts("YES");

  if (n == 1) {
    printf("%d %d\n", a, b);
    return 0;
  }

  vector<int> vec[5];

  vec[0].push_back(0);
  vec[0].push_back(1);

  for (int i = 0; i < 4; i++) {
    for (int p = 0; p < vec[i].size(); p++) {
      for (int q = 0; q < vec[i].size(); q++) {
        int r;
        if (p % 2 == 0)
          r = q;
        else
          r = vec[i].size() - q - 1;

        vec[i + 1].push_back((vec[i][p] << (1 << i)) + vec[i][r]);
      }
    }
  }

  n--;

  vector<int> vec1;

  for (int i = 0; i < 5; i++) {
    if (n & (1 << i)) {
      if (vec1.size() == 0) {
        vec1 = vec[i];
        continue;
      }

      vector<int> vec2;

      for (int p = 0; p < vec[i].size(); p++) {
        for (int q = 0; q < vec1.size(); q++) {
          int r;
          if (p % 2 == 0)
            r = q;
          else
            r = vec1.size() - q - 1;

          vec2.push_back((vec1[r] << (1 << i)) + vec[i][p]);
        }
      }

      vec1 = vec2;
    }
  }

  int y = -1, x = -1;

  for (int i = 0; i < vec1.size(); i++) {
    int q;
    if (i % 2 == 0) {
      q = __builtin_popcount(vec1[0] ^ vec1[i]) + 1;
    } else {
      q = __builtin_popcount(vec1[0] ^ vec1[i]);
    }

    if (q == pp) {
      y = i % 2 == 0;
      x = i;
      break;
    }
  }

  assert(y != -1);

  vector<int> vec2;

  for (int i = 0; i < x; i++) {
    if (i % 2 == 0)
      vec2.push_back(vec1[i] * 2 + 0);
    vec2.push_back(vec1[i] * 2 + 1);
    if (i % 2 == 1)
      vec2.push_back(vec1[i] * 2 + 0);
  }

  for (int i = x; i < vec1.size(); i++) {
    if (y == 0)
      vec2.push_back(vec1[i] * 2 + 1);
    if (y == 1)
      vec2.push_back(vec1[i] * 2 + 0);
  }

  for (int i = vec1.size() - 1; i >= x; i--) {
    if (y == 0)
      vec2.push_back(vec1[i] * 2 + 0);
    if (y == 1)
      vec2.push_back(vec1[i] * 2 + 1);
  }

  n++;

  set<int> t1, t2;

  for (int i = 0; i < n; i++) {
    int m = vec2.size();
    int p = vec2[0] & (1 << i);
    int q = vec2[m - 1] & (1 << i);

    int r = a & (1 << i);
    int s = b & (1 << i);

    if (p != q)
      t1.insert(i);
    if (r != s)
      t2.insert(i);
  }

  int cur = 0;
  for (int i = 0; i < n; i++) {
    if (t1.find(i) != t1.end())
      continue;
    while (t2.find(cur) != t2.end())
      cur++;

    conv[i] = cur++;
  }

  auto it1 = t1.begin();
  auto it2 = t2.begin();

  while (it1 != t1.end()) {
    conv[*it1] = *it2;
    it1++;
    it2++;
  }

  bool f[20];

  int tmp = ff(vec2[0]);

  for (int i = 0; i < n; i++) {
    int p = tmp & (1 << i);
    int q = a & (1 << i);

    f[i] = p ^ q;
  }

  int prev = -1;

  debug(vec2.size());

  for (int i = 0; i < vec2.size(); i++) {
    int res = ff(vec2[i]);

    for (int j = 0; j < n; j++) {
      if (f[j])
        res ^= 1 << j;
    }

    printf("%d ", res);

    assert(prev == -1 || __builtin_popcount(res ^ prev) == 1);
    prev = res;

    if (i == 0)
      assert(a == res);
  }
  assert(b == prev);

  puts("");

  sort(vec1.begin(), vec1.end());

  for (int i = 0; i < n; i++) {
    assert(vec1[i] == i);
  }

  return 0;
}