#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
template <typename A, typename B>
ostream& operator<<(ostream& os, const pair<A, B>& p) {
  return os << '{' << p.first << ',' << p.second << '}';
}
template <typename T>
struct point {
  T x, y;
  point(T xx = 0, T yy = 0) : x(xx), y(yy) {}
  T len2() const { return x * x + y * y; }
  double len() const { return sqrt(double(len2())); }
  bool operator==(const point<T>& p) const { return x == p.x && y == p.y; }
};
template <typename T>
point<T> operator+(const point<T>& a, const point<T>& b) {
  return point<T>(a.x + b.x, a.y + b.y);
}
template <typename T>
point<T> operator-(const point<T>& a, const point<T>& b) {
  return point<T>(a.x - b.x, a.y - b.y);
}
template <typename T>
T scal(const point<T>& a, const point<T>& b) {
  return a.x * b.x + a.y * b.y;
}
template <typename T>
T vect(const point<T>& a, const point<T>& b) {
  return a.x * b.y - a.y * b.x;
}
template <typename T>
ostream& operator<<(ostream& os, const point<T>& p) {
  return os << '(' << p.x << ',' << p.y << ')';
}
template <typename T>
T gcd(T a, T b) {
  return a > 0 ? gcd(b % a, a) : b;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& c) {
  for (typename vector<T>::const_iterator it = c.begin(); it != c.end(); ++it) {
    os << *it;
  }
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& c) {
  for (typename set<T>::const_iterator it = c.begin(); it != c.end(); ++it) {
    os << *it;
  }
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const multiset<T>& c) {
  for (typename multiset<T>::const_iterator it = c.begin(); it != c.end();
       ++it) {
    os << *it;
  }
  return os;
}
template <typename K, typename T>
ostream& operator<<(ostream& os, const multimap<K, T>& c) {
  for (typename multimap<K, T>::const_iterator it = c.begin(); it != c.end();
       ++it) {
    os << *it;
  }
  return os;
}
template <typename K, typename T>
ostream& operator<<(ostream& os, const map<K, T>& c) {
  for (typename map<K, T>::const_iterator it = c.begin(); it != c.end(); ++it) {
    os << *it;
  }
  return os;
}
pair<int, int> transpose(pair<int, int> q) {
  return pair<int, int>(q.second, q.first);
}
pair<int, int> get(int n, int l) {
  if (n == 1) {
    if (l == 0) return pair<int, int>(0, 0);
    if (l == 1) {
      return pair<int, int>(0, 1);
    }
    if (l == 2) return pair<int, int>(1, 1);
    if (l == 3) return pair<int, int>(1, 0);
    assert(0);
  }
  int lim = (1 << (n * 2));
  int lim4 = lim >> 2;
  if (l >= lim4 * 2) {
    pair<int, int> q = get(n, lim - 1 - l);
    q.first = (1 << (n)) - 1 - q.first;
    return q;
  }
  if (l < lim4) {
    return transpose(get(n - 1, l));
  } else if (l < lim4 * 2) {
    pair<int, int> q = get(n - 1, l - lim4);
    q.second += (1 << (n - 1));
    return q;
  } else
    assert(0);
}
int main() {
  int n;
  cin >> n;
  int l;
  cin >> l;
  pair<int, int> q = get(n, l);
  printf("%d %d\n", q.first, q.second);
  return 0;
}
