//#undef _DEBUG
//#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace std::chrono;
#define int long long //todo 消したら動かない intの代わりにsignedを使う
#define ll long long
auto start_time = system_clock::now();
auto past_time = system_clock::now();

#define debugName(VariableName) # VariableName
//最大引数がN
#define over2(o1, o2, name, ...) name
#define over3(o1, o2, o3, name, ...) name
#define over4(o1, o2, o3, o4, name, ...) name
#define over5(o1, o2, o3, o4, o5, name, ...) name
#define over6(o1, o2, o3, o4, o5, o6, name, ...) name
#define over7(o1, o2, o3, o4, o5, o6, o7, name, ...) name
#define over8(o1, o2, o3, o4, o5, o6, o7, o8, name, ...) name
#define over9(o1, o2, o3, o4, o5, o6, o7, o8, o9, name, ...) name
#define over10(o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, name, ...) name

#define rep(i,a,b) for(int i=a;i<b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,a) for(auto &i:a)
#define all(x) (x).begin(),(x).end()

#define rand xor128_
/*@formatter:on*/
unsigned long xor128_(void) {
    static unsigned long x = 123456789, y = 362436069, z = 521288629, w = 88675123;
    unsigned long t;
    t = (x ^ (x << 11));
    x = y;
    y = z;
    z = w;
    return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
}
/*@formatter:on*/
ll rand(ll min, ll max) {
    assert(min <= max);
    if (min >= 0 && max >= 0) { return rand() % (max + 1 - min) + min; } else if (max < 0) { return -rand(-max, -min); } else { if (rand() % 2) { return rand(0, max); } else { return -rand(0, -min); }}
}
#define sz(a) ((int)a.size())
const int inf = (int) 1e9 + 100;

/*@formatter:off*/
//@起動時
struct initon {
    initon() {
        cin.tie(0);
        ios::sync_with_stdio(false);
        cout.setf(ios::fixed);
        cout.precision(16);
        srand((unsigned) clock() + (unsigned) time(NULL));
    };
} initonv;
#define pre prev
#define nex next


//hashを共有したくない場合、中に書く
const uint64_t base = rand((uint64_t) 868491463, ((uint64_t) 1 << 61) - 1 - 1);

//安全で爆速なrollinghash
class roll {
    /*@formatter:on*/
    static constexpr uint64_t mask30 = ((uint64_t) 1 << 30) - 1;
    static constexpr uint64_t mask31 = ((uint64_t) 1 << 31) - 1;
    static constexpr uint64_t mask61 = ((uint64_t) 1 << 61) - 1;
    static constexpr uint64_t offset = mask61 * 7;
    static constexpr uint64_t mod(const uint64_t x) {
        const uint64_t y = (x >> 61) + (x & mask61);
        return y >= mask61 ? y - mask61 : y;
    }
    static constexpr uint64_t mul(const uint64_t x, const uint64_t y) {
        const uint64_t xh = x >> 31, xl = x & mask31;
        const uint64_t yh = y >> 31, yl = y & mask31;
        const uint64_t z = xl * yh + xh * yl;
        const uint64_t zh = z >> 30, zl = z & mask30;
        return xh * yh * 2 + zh + (zl << 31) + xl * yl;
    }
    const std::size_t siz;
    vector<uint64_t> pow, h;
public:
    template<typename T> roll(T &A) : siz(sz(A)), pow(siz + 1, 1), h(siz + 1, 0) { for (std::size_t i = 1; i <= siz; i++) { pow[i] = mod(mul(pow[i - 1], base)), h[i] = mod(mul(h[i - 1], base) + A[i - 1]); }}
    uint64_t operator()(const std::size_t l, const std::size_t r) { return mod(h[r] + offset - mul(h[l], pow[r - l])); }
    uint64_t operator()(int r = inf) { return operator()(0, min((int)siz, r)); }
    // get lcp of S[a:] and T[b:]
    //接頭語がどれだけ一致するか
    //範囲の重複を含む
    int lcp_dup(int a, int b) {
        int len = min((int) siz - a, (int) siz - b);
        int low = 0, high = len;
        while (high - low > 1) {
            int mid = (low + high) >> 1;
            if (operator()(a, a + mid) != operator()(b, b + mid)) high = mid; else low = mid;
        }
        return low;
    }
    //重複を認めない
    int lcp_not(int a, int b) { return min(lcp_dup(a, b), b - a); }//@formatter:on
};
//動かない場合roll2
//roll ro(list);
//---------------------------------------------------------------------------------------------------
template<int MOD> struct ModInt {
    static const int Mod = MOD; unsigned x; ModInt() : x(0) { }
    ModInt(signed sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
    ModInt(signed long long sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
    int get() const { return (int)x; }
    ModInt& operator+=(ModInt that) { if ((x += that.x) >= MOD) x -= MOD; return *this; }
    ModInt& operator-=(ModInt that) { if ((x += MOD - that.x) >= MOD) x -= MOD; return *this; }
    ModInt& operator*=(ModInt that) { x = (unsigned long long)x * that.x % MOD; return *this; }
    ModInt& operator/=(ModInt that) { return *this *= that.inverse(); }
    ModInt operator+(ModInt that) const { return ModInt(*this) += that; }
    ModInt operator-(ModInt that) const { return ModInt(*this) -= that; }
    ModInt operator*(ModInt that) const { return ModInt(*this) *= that; }
    ModInt operator/(ModInt that) const { return ModInt(*this) /= that; }
    ModInt inverse() const {
        long long a = x, b = MOD, u = 1, v = 0;
        while (b) { long long t = a / b; a -= t * b; std::swap(a, b); u -= t * v; std::swap(u, v); }
        return ModInt(u);
    }
    bool operator==(ModInt that) const { return x == that.x; }
    bool operator!=(ModInt that) const { return x != that.x; }
    ModInt operator-() const { ModInt t; t.x = x == 0 ? 0 : Mod - x; return t; }
};
template<int MOD> ModInt<MOD> operator^(ModInt<MOD> a, unsigned long long k) {
    ModInt<MOD> r = 1; while (k) { if (k & 1) r *= a; a *= a; k >>= 1; } return r;
}
int getrandmax() {
    static uint32_t y = time(NULL);
    y ^= (y << 13); y ^= (y >> 17);
    y ^= (y << 5);
    return abs((int)y);
}
int getrand(int l, int r) { // [l, r]
    return getrandmax() % (r - l + 1) + l;
}
typedef ModInt<1000000007> mint1;
typedef ModInt<1000000009> mint2;
int primes[10] = { 10007, 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093 };
bool isShuffle = false;
struct RollingHash {
    mint1 p1; mint2 p2;
    int n;
    vector<mint1> m1; vector<mint2> m2;
    vector<mint1> v1; vector<mint2> v2;

    RollingHash() {
        if (!isShuffle) {
            rep(i, 0, 101) { int a = getrand(0, 9); int b = getrand(0, 9); swap(primes[a], primes[b]); }
            isShuffle = true;
        }
        p1 = primes[0], p2 = primes[1];
    }

    void init(string s, char o = 'a') {
        vector<int> v;
        fore(c, s) v.push_back(c - o);
        init(v);
    }

    void init(vector<int> s) {
        n = s.size();
        m1.resize(n); m2.resize(n); v1.resize(n); v2.resize(n);

        m1[0] = 1; m2[0] = 1;
        v1[0] = s[0]; v2[0] = s[0];

        rep(i, 1, n) {
            m1[i] = m1[i - 1] * p1;
            m2[i] = m2[i - 1] * p2;
            v1[i] = v1[i - 1] + m1[i] * s[i];
            v2[i] = v2[i - 1] + m2[i] * s[i];
        }
    }
    inline pair<mint1, mint2> hash(int l, int r) { // s[l..r]
        assert(l <= r); assert(r < n);
        mint1 a = v1[r];
        if (l) a -= v1[l - 1];
        a *= m1[n - 1 - r];

        mint2 b = v2[r];
        if (l) b -= v2[l - 1];
        b *= m2[n - 1 - r];

        return { a, b };
    }
    inline ll llhash(int l, int r) { // s[l..r]
        auto h = hash(l, r);
        return 1LL * h.first.get() * h.second.Mod + h.second.get();
    }
};




using vi = vector<int>;
int N;

void solve() {
    cin >> N;
    vi A(N), B(N), A2(N), B2(N);
    rep(i, 0, N)cin >> A[i];
    rep(i, 0, N)cin >> B[i];

    rep(i, 0, N)A2[i] = A[i] ^ A[(i + 1) % N];
    rep(i, 0, N)B2[i] = B[i] ^ B[(i + 1) % N];

    vector<int> v;
    rep(i, 0, N)v.push_back(A2[i]);
    rep(i, 0, N)v.push_back(A2[i]);
    rep(i, 0, N)v.push_back(B2[i]);

    RollingHash rh;
    rh.init(v);
    rep(k, 0, N)
    if (rh.hash(k, k + N-1) == rh.hash(N * 2, N * 2 + N-1)) {
        int x = A[k] ^B[0];
        cout<<k<<" "<<x<<endl;
    }
}


auto my(ll n, vi &a) {
    return 0;
}

auto sister(ll n, vi &a) {
    ll ret = 0;
    return ret;
}

signed main() {
    solve();
    return 0;
};


Measured memory_bytes: 27112