import std.conv, std.functional, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.complex, std.container, std.math, std.numeric, std.range, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }


enum LIM = 60;
enum MASK_EVEN = 0x_5555_5555_5555_5555UL;
enum MASK_ODD  = 0x_aaaa_aaaa_aaaa_aaaaUL;

// for old compiler...
int popcnt(ulong x) {
  return core.bitop.popcnt(cast(uint)(x & 0x_ffff_ffffUL)) + core.bitop.popcnt(cast(uint)(x >> 32));
}

int N;
long[] X, Y;

void main() {
  auto binom = new int[][LIM];
  foreach (n; 0 .. LIM) {
    binom[n] = new int[n + 1];
    binom[n][0] = binom[n][n] = 1;
    foreach (k; 1 .. n) {
      binom[n][k] = binom[n - 1][k - 1] + binom[n - 1][k];
    }
  }
  auto cnt3 = new int[][][](LIM, LIM, 3);
  foreach (a0; 0 .. LIM) foreach (a1; 0 .. LIM) {
    foreach (b0; 0 .. a0 + 1) foreach (b1; 0 .. a1 + 1) {
      cnt3[a0][a1][(b0 + 2 * b1) % 3] += binom[a0][b0] * binom[a1][b1];
    }
  }
  debug {
    foreach (a0; 0 .. 4) foreach (a1; 0 .. 4) {
      writefln("cnt3[%s][%s] = %s", a0, a1, cnt3[a0][a1]);
    }
  }
  
  try {
    for (; ; ) {
      N = readInt();
      X = new long[N];
      Y = new long[N];
      foreach (i; 0 .. N) {
        X[i] = readLong();
        Y[i] = readLong();
      }
      
      long y0;
      long x0, x1;
      foreach (i; 0 .. N) {
        chmin(y0, Y[i]);
        chmin(x0, X[i]);
        chmax(x1, X[i] + Y[i] - y0);
      }
      debug {
        writefln("y0 = %s", y0);
        writefln("[x0, x1] = [%s, %s]", x0, x1);
      }
      
      int calc(long x) {
        int ret;
        foreach (i; 0 .. N) {
          const d = Y[i] - y0;
          const k = x - X[i];
          if (0 <= k && k <= d && (d & k) == k) {
            ret ^= 1;
          }
        }
        return ret;
      }
      int calc3(int s, long xL, long xR) {
        debug {
          int brt;
          foreach (x; xL .. xR + 1) {
            if ((x - s) % 3 == 0) {
              foreach (i; 0 .. N) {
                const d = Y[i] - y0;
                const k = x - X[i];
                if (0 <= k && k <= d && (d & k) == k) {
                  ++brt;
                }
              }
            }
          }
          writefln("calc3 %s [%s, %s] = %s", s, xL, xR, brt);
        }
        int ret;
        foreach (i; 0 .. N) {
          // count k s.t. kL <= k <= kR, k == t (mod 3), C(d, k) == 1 (mod 2)
          const d = Y[i] - y0;
          const kL = max(xL - X[i], 0);
          const kR = min(xR - X[i], d);
          const t = cast(int)(((s - X[i]) % 3 + 3) % 3);
          if (kL <= kR) {
            /*
            auto dp = new int[][][][](LIM + 1, 2, 2, 3);
            foreach (a; 0 .. 2) foreach (b; 0 .. 2) {
              dp[0][a][b][t] = 1;
            }
            foreach (pos; 0 .. LIM) {
              const dM = (d >> pos) & 1;
              const kLM = (kL >> pos) & 1;
              const kRM = (kR >> pos) & 1;
              foreach (a; 0 .. 2) foreach (b; 0 .. 2) foreach (c; 0 .. 3) {
                foreach (z; 0 .. 2) {
                  if ((a || kLM <= z) && (b || z <= kRM) && ((dM & z) == z)) {
                    dp[pos + 1][a][b][c] += dp[pos][a || kLM < z][b || z < kRM][(c + ((pos & 1) ? 2 : 1) * z) % 3];
                  }
                }
              }
            }
            debug {
              writefln("  d = %s, [kL, kR] = [%s, %s], t = %s: %s", d, kL, kR, t, dp[0][0][0][0]);
            }
            ret += dp[LIM][0][0][0];
            */
            
            // k < kLim
            int solve(long kLim) {
              int sum;
              foreach (pos; 0 .. LIM) {
                if ((kLim >> pos) & 1) {
                  const high = kLim & ~((1L << (pos + 1)) - 1);
                  if ((d & high) == high) {
                    const low = d & ((1L << pos) - 1);
                    const a0 = popcnt(low & MASK_EVEN);
                    const a1 = popcnt(low & MASK_ODD);
                    const b0 = popcnt(high & MASK_EVEN);
                    const b1 = popcnt(high & MASK_ODD);
                    sum += cnt3[a0][a1][(t + 2 * b0 + b1) % 3];
                  }
                }
              }
              return sum;
            }
            ret += solve(kR + 1);
            ret -= solve(kL);
          }
        }
        debug {
          writefln("  ret = %s & 1", ret);
        }
        return ret & 1;
      }
      
      long[] ans;
      foreach (s; 0 .. 3) {
        if (calc3(s, x0, x1)) {
          long lo = x0, hi = x1 + 1;
          for (; lo + 1 < hi; ) {
            const mid = (lo + hi) / 2;
            calc3(s, lo, mid - 1) ? (hi = mid) : (lo = mid);
          }
          assert((lo - s) % 3 == 0);
          assert(calc(lo));
          long x = lo;
          foreach_reverse (e; 0 .. LIM) {
            if (calc(x - (1L << e))) {
              x -= (1L << e);
            }
          }
          long h;
          foreach (e; 0 .. LIM) {
            if (calc(x + (1L << e))) {
              h |= 1L << e;
            }
          }
          ans = [x, y0 + h];
          break;
        }
      }
      assert(ans != []);
      writeln(ans[0], " ", ans[1]);
    }
  } catch (EOFException e) {
  }
}
