#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <map>
#include <set>
#include <stack>
#include <tuple>
#include <deque>
#include <numeric>
#include <bitset>
#include <iomanip>
#include <cassert>
#include <chrono>
#include <random>
#include <limits>
#include <iterator>
#include <functional>
#include <sstream>
#include <complex>
using namespace std;

#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)

typedef long long ll;
typedef uint64_t ull;
typedef pair<int, int> P;
typedef pair<int, double> Pid;
typedef pair<double, int> Pdi;
typedef pair<ll, int> Pl;
typedef pair<ll, ll> Pll;
typedef pair<int, pair<int, int>> PP;
typedef pair<P, int> PPi;
constexpr double PI = 3.1415926535897932;   // acos(-1)
constexpr double EPS = 1e-9;
constexpr int INF = 1001001001;
constexpr int mod = 1e+9 + 7;
// constexpr int mod = 998244353;

template<typename T>
struct KMP{
    const T& word;
    int word_sz;
    // 単語に関する表
    // table[i] := S[0, i) において、prefix と suffix が一致している最大の長さ
    // つまり、S[0, table[i]), S[i-table[i], i) が等しいことを表す。
    // S[0, 0) では定義できないので、table[0] = -1 とする。
    // table[1] では、S[i-table[i], i) = S[1, 1) となるが、この場合は 1 文字も一致していないとみなして、table[1] = 0
    vector<int> table;

    KMP(const T &s) : word(s), word_sz(s.size()){
        table.resize(word_sz + 1);
        table[0] = -1;
        int len = -1;       // 現在の prefix と suffix が等しい時の prefix の長さを表す。
        for(int i = 0; i < word_sz; ++i){
            // 次の文字が等しくなければ、len を短くしていく。
            // 今見ている prefix だけを見て、
            // その中での prefix' と suffix' が一致する最長のものが次の len の候補となる。
            // prefix の prefix'(=suffix') は、suffix の後ろの部分とも一致する。
            while(len >= 0 && word[i] != word[len]) len = table[len];
            table[i + 1] = ++len;
        }
    }

    vector<int> get_list(const T& str){
        vector<int> res;
        int st = 0;     // 今見ている部分文字列の先頭
        int len = 0;    // 今見ている部分文字列の長さ
        int n = str.size();
        while(st + len < n){
            if(word[len] == str[st + len]){
                if(++len == word_sz){
                    res.push_back(st);
                    st = st + len - table[len];
                    len = table[len];
                }
            }
            else{
                st = st + len - table[len];
                if(len > 0) len = table[len];
            }
        }
        return res;
    }

    void print(){
        int sz = table.size();
        for(int i = 0; i < sz; ++i){
            cerr << table[i];
            cerr << ((i == sz - 1) ? "\n" : " ");
        }
    }
};

vector<int> adjacent_xor(vector<int>& v){
    int sz = v.size();
    vector<int> res(sz);
    for(int i = 0; i < sz - 1; ++i) res[i] = v[i] ^ v[i + 1];
    res[sz - 1] = v[sz - 1] ^ v[0];
    return res;
}
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int n;
    cin >> n;
    vector<int> a(n), b(n);
    for(int i = 0; i < n; ++i)  cin >> a[i];
    for(int i = 0; i < n; ++i)  cin >> b[i];
    vector<int> axor = adjacent_xor(a);
    vector<int> bxor = adjacent_xor(b);
    bxor.insert(bxor.end(), bxor.begin(), bxor.end());
    // for(int i = 0; i < n; ++i)  cerr << axor[i] << " ";
    // cerr << "\n";
    // for(int i = 0; i < n * 2; ++i)  cerr << bxor[i] << " ";
    // cerr << "\n";
    KMP<vector<int>> kmp(axor);
    vector<int> List = kmp.get_list(bxor);
    // for(int k : List)   cerr << k << " ";
    // cerr << "\n";
    int sz = List.size();
    vector<int> ks(sz);
    for(int i = 0; i < sz; ++i) ks[i] = n - List[i];
    sort(ks.begin(), ks.end());
    for(int k : ks){
        if(k >= n)  break;
        int x = a[k] ^ b[0];
        cout << k << " " << x << "\n";
    }
}

Measured memory_bytes: 9968