Language: C++

// #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
using namespace std;
using ll = long long int;
using int64 = long long int;
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const int INF = 1LL << 29;
const ll LONGINF = 1LL << 60;
const ll MOD = 1000000007LL;

// O(n log n) で構築するやつ
// ・getIdx(i) := Suffix を辞書順に並べたときに i 番目に来るものは、元の文字列で何番目のインデックスからはじめた Suffix か？
// ・getLCP(i) := SuffixArray 上で i 番目と i+1 番目の要素の最長共通接頭辞はいくらか？
// ・is_greater: 辞書順 i 番目の Suffix がパターン文字列より大きいか見る
// ・is_less: 辞書順 i 番目の Suffix がパターン文字列より小さいか見る
// ・binary_search_greater: パターン文字列より大きい Suffix でインデックス最小のもの
// ・binary_search_less: パターン文字列より小さい Suffix でインデックス最小のもの
const int ALPH = 256;
struct SuffixArray {
private:
    string s;
    vector<int> rec, lcp, cnt;
    int len, cnt_size;
public:
    SuffixArray(string s_) : s(s_) {
        s += "$"; // 辞書順で最も小さいダミー文字
        len = s.length();
        cnt_size = max(ALPH, len); cnt.resize(cnt_size);
        rec = getArray();
        lcp = getLCPArray();
    }

    void dump_array(vector<int> &indices, vector<int> &classes) {
        fprintf(stderr, "# debug\n");
        fprintf(stderr, "# indices:");
        for(int i=0; i<len; i++) fprintf(stderr, " %d", indices[i]);
        fprintf(stderr, "\n");
        fprintf(stderr, "# classes:");
        for(int i=0; i<len; i++) fprintf(stderr, " %d", classes[i]);
        fprintf(stderr, "\n");
    }
    
    vector<int> getArray() {
        vector<int> indices(len), prev_idx(len);
        vector<int> classes(len), prev_cls(len);
        vector<int> tmp_val(len);

        // k == 0 はカウントソートのみ
        for(int i=0; i<len; i++) {
            cnt[ s[i] ]++;
        }
        for(int i=1; i<cnt_size; i++) {
            cnt[i] += cnt[i-1];
        }
        for(int i=len-1; i>=0; i--) {
            indices[ --cnt[ s[i] ] ] = i;
        }
        for(int i=1; i<len; i++) {
            int pena = (s[ indices[i] ] != s[ indices[i-1] ]);
            classes[ indices[i] ] = classes[ indices[i-1] ] + pena;
        }
        
        for(int k=0; (1 << k) < len; k++) {
            swap(indices, prev_idx);
            swap(classes, prev_cls);
            for(int i=0; i<len; i++) {
                // 後半だけソート済みにしたものを indices に代入
                prev_idx[i] = prev_idx[i] - (1 << k);
                if(prev_idx[i] < 0) prev_idx[i] += len;
                tmp_val[i] = prev_cls[ prev_idx[i] ];
            }

            // 前半についてカウントソート
            fill(cnt.begin(), cnt.end(), (int)0);
            for(int i=0; i<len; i++) {
                cnt[ tmp_val[i] ]++;
            }
            for(int i=1; i<cnt_size; i++) {
                cnt[i] += cnt[i-1];
            }
            for(int i=len-1; i>=0; i--) {
                indices[ --cnt[ tmp_val[i] ] ] = prev_idx[i];
            }
            classes[ indices[0] ] = 0;
            for(int i=1; i<len; i++) {
                int shift = (1 << k);
                pair<int, int> pre(prev_cls[ indices[i-1] ], prev_cls[ (indices[i-1] + shift) % len ]);
                pair<int, int> cur(prev_cls[ indices[i  ] ], prev_cls[ (indices[i  ] + shift) % len ]);
                int pena = (pre != cur);
                classes[ indices[i] ] = classes[ indices[i-1] ] + pena;
            }
        }
        return indices;
    }

    int size() {
        return rec.size();
    }
    // Suffix を辞書順に並べたときに idx 番目に来るものは、元の文字列で何番目のインデックスからはじめた Suffix か？
    int getIdx(int idx) {
        assert(0 <= idx and idx < size());
        return rec[idx];
    }
    // SuffixArray 上で idx 番目と idx+1 番目の要素の最長共通接頭辞はいくらか？
    int getLCP(int idx) {
        assert(0 <= idx and idx < size());
        return lcp[idx];
    }
    
    // 元の文字列の idx 番目以降の接尾辞は、パターン文字列 p に比べて大きいか？
    bool is_greater(string &p, int idx) {
        idx = getIdx(idx);
        int N = size(), M = p.size(), x, y;
        for(x=idx, y=0; x<N and y<M; x++, y++) {
            if(s[x] > p[y]) return true;
            if(s[x] < p[y]) return false;
        }
        return y >= M and x < N;
    }

    // 元の文字列の idx 番目以降の接尾辞は、パターン文字列 p に比べて小さいか？
    bool is_less(string &p, int idx) {
        idx = getIdx(idx);
        int N = size(), M = p.size(), x, y;
        for(x=idx, y=0; x<N and y<M; x++, y++) {
            if(s[x] < p[y]) return true;
            if(s[x] > p[y]) return false;
        }
        return x >= N and y < M;
    }
    
    // SA 配列上で、p より大きくなる要素であって最小のもの
    // そのような要素が存在しなければ -1
    int binary_search_greater(string &p) {
        int lb = -1, ub = len;
        while(ub - lb > 1) {
            int mid = (ub + lb) / 2;
            if(is_greater(p, mid)) ub = mid;
            else lb = mid;
        }

        if(ub == len) return -1;
        return ub;
    }

    // SA 配列上で、p より小さくなる要素であって最大のもの
    // そのような要素が存在しなければ -1
    int binary_search_less(string &p) {
        int lb = -1, ub = len;
        while(ub - lb > 1) {
            int mid = (ub + lb) / 2;
            if(is_less(p, mid)) lb = mid;
            else ub = mid;
        }
        if(lb == -1) return -1;
        return lb;
    }

    // LCP[i] := SA 配列上の i 番目と i+1 番目の最長共通接頭辞
    vector<int> getLCPArray() {
        vector<int> rank(len);
        for(int i=0; i<len; i++) {
            rank[ rec[i] ] = i;
        }

        vector<int> res(len, -1);
        int cons = 0;
        // 空文字列に関しては探索しない！
        for(int i=0; i+1<len; i++) {
            // i 文字目から始まる接尾辞に対して
            // SA 配列上で直前の要素をもってくる
            int pre = rec[ rank[i] - 1 ], cur = i;

            while(s[cur + cons] == s[pre + cons]) cons++;
            res[ rank[i] - 1 ] = cons;
            cons = max<int>(0, cons - 1);
        }
        return res;
    }
};

/*
// Suffix Array: 構築 O(|S| log^2 |S|)
// 蟻本の実装と多分同じ
struct SuffixArray {
    int N, k;
    vector<int> rank, sa;
    string s;

    SuffixArray(string t) {
        s = t, k = 1, N = t.length();
        rank = sa = vector<int>(N+1);
        build();
    }

    bool compare_sa(int i, int j) {
        if(rank[i] != rank[j]) return rank[i] < rank[j];
        else {
            int vi = (i+k <= N ? rank[i+k] : -1);
            int vj = (j+k <= N ? rank[j+k] : -1);
            return vi < vj;
        }
    }

    void build() {
        for(int i=0; i<=N; i++) {
            sa[i] = i;
            rank[i] = (i < N ? s[i] : -1);
        }

        for(k=1; k<=N; k*=2) {
            sort(sa.begin(), sa.end(), [&](int i, int j) {
                return compare_sa(i, j);
            });

            vector<int> tmp(N+1, 0);
            tmp[ sa[0] ] = 0;
            for(int i=1; i<=N; i++) {
                tmp[ sa[i] ] = tmp[ sa[i-1] ] + (compare_sa(sa[i-1], sa[i]) ? 1 : 0);
            }

            swap(rank, tmp);
        }
    }

    string get_substr(int idx) {
        return s.substr(sa[idx]);
    }

    void output() {
        for(int i=0; i<=N; i++) {
            fprintf(stderr, "idx = %3d, str = %s\n", i, get_substr(i).c_str());
        }
    }

    int operator[](int idx) const {
        return sa[idx];
    }
};
*/


const int B = 30;

int main() {
    int N; cin >> N;
    vector<string> as(B, ""), bs(B, ""), bs_rev(B, "");
    for(int i=0; i<N; i++) {
        ll v; cin >> v;
        for(int k=0; k<B; k++) {
            as[k] += (char)('0' + (v >> k & 1));
        }
    }
    for(int i=0; i<N; i++) {
        ll v; cin >> v;
        for(int k=0; k<B; k++) {
            bs[k] += (char)('0' + (v >> k & 1));
            bs_rev[k] += (char)('0' + !(v >> k & 1));
        }
    }

    vector<int> shift_a(B), shift_b(B), shift_b_rev(B);
    for(int x=0; x<B; x++) {
        string s = as[x] + as[x];
        SuffixArray sa(s);
        for(size_t i=0; i<=s.size(); i++) {
            int res = sa.getIdx(i);
            if(0 <= res and res < as[x].size()) {
                shift_a[x] = res;
                break;
            }
        }

        as[x] = as[x].substr(shift_a[x]) + as[x].substr(0, shift_a[x]);
        // fprintf(stderr, "as = %s, res = %d\n", as[x].c_str(), shift_a[x]);
    }

    for(int x=0; x<B; x++) {
        string s = bs[x] + bs[x];
        SuffixArray sa(s);
        for(size_t i=0; i<=s.size(); i++) {
            int res = sa.getIdx(i);
            if(0 <= res and res < bs[x].size()) {
                shift_b[x] = res;
                break;
            }
        }
        bs[x] = bs[x].substr(shift_b[x]) + bs[x].substr(0, shift_b[x]);
        // fprintf(stderr, "bs = %s, re = %d\n", bs[x].c_str(), shift_b[x]);
    }

    for(int x=0; x<B; x++) {
        string s = bs_rev[x] + bs_rev[x];
        SuffixArray sa(s);
        for(size_t i=0; i<=s.size(); i++) {
            int res = sa.getIdx(i);
            if(0 <= res and res < bs_rev[x].size()) {
                shift_b_rev[x] = res;
                break;
            }
        }
        bs_rev[x] = bs_rev[x].substr(shift_b_rev[x]) + bs_rev[x].substr(0, shift_b_rev[x]);
        // fprintf(stderr, "bs_rev = %s, res = %d\n", bs_rev[x].c_str(), shift_b_rev[x]);
    }

    // シフト量としてありえるもの
    vector< vector<int> > valid(B), valid_rev(B);
    vector< vector<int> > divs(B);
    {
        vector<int> tmp;
        for(int i=1; i*i<=N; i++) {
            if(N % i == 0) {
                tmp.emplace_back(i);
                if(N / i != i) tmp.emplace_back(N / i);
            }
        }
        sort(tmp.begin(), tmp.end());

        for(int d : tmp) {
            for(int i=0; i<B; i++) {
                bool valid = true;
                string t = as[i].substr(0, d);
                for(size_t j=0; j<as[i].size(); j+=d) {
                    valid &= (t == as[i].substr(j, d));
                }
                if(valid) divs[i].emplace_back(d);
            }
        }
    }
    
    for(int x=0; x<B; x++) {
        if(as[x] == bs[x]) {
            // fprintf(stderr, "equal: %d\n", x);
            int shift = (shift_a[x] - shift_b[x] + N) % N;
            valid[x].emplace_back(shift);

            int orig = shift;
            for(auto d : divs[x]) {
                while(true) {
                    (shift += d) %= N;
                    if(orig == shift) break;
                    valid[x].emplace_back(shift);
                }
                shift = orig;
            }
        }
        if(as[x] == bs_rev[x]) {
            // fprintf(stderr, "equal rev: %d\n", x);
            int shift = (shift_a[x] - shift_b_rev[x] + N) % N;
            valid_rev[x].emplace_back(shift);

            int orig = shift;
            for(auto d : divs[x]) {
                while(true) {
                    (shift += d) %= N;
                    if(orig == shift) break;
                    valid_rev[x].emplace_back(shift);
                }
                shift = orig;
            }
        }
    }

    for(int i=0; i<B; i++) {
        sort(valid[i].begin(), valid[i].end());
        valid[i].erase(unique(valid[i].begin(), valid[i].end()), valid[i].end());
        
        sort(valid_rev[i].begin(), valid_rev[i].end());
        valid_rev[i].erase(unique(valid_rev[i].begin(), valid_rev[i].end()), valid_rev[i].end());
    }
    
    vector< vector< vector<int> > > cand(N, vector< vector<int> >(B));
    for(int i=0; i<B; i++) {
        for(auto k : valid[i]) cand[k][i].emplace_back(0);
    }
    for(int i=0; i<B; i++) {
        for(auto k : valid_rev[i]) cand[k][i].emplace_back(1);
    }

    vector< pair<int, int> > ans;
    auto dfs = [&](auto&& f, int idx, int b, int X) -> void {
        if(b == B) {
            ans.emplace_back(idx, X);
            return;
        }
        for(auto e : cand[idx][b]) {
            // fprintf(stderr, "cand %d %d: %d\n", idx, b, e);
            X ^= (e << b);
            f(f, idx, b+1, X);
            X ^= (e << b);
        }
    };

    for(int i=0; i<N; i++) {
        bool ok = true;
        for(int j=0; j<B; j++) ok &= (cand[i][j].size > 0);
        if(ok) dfs(dfs, i, 0, 0);
    }

    sort(ans.begin(), ans.end());
    for(auto e : ans) {
        int k, x; tie(k, x) = e;
        printf("%d %d\n", k, x);
    }
    
    /*
    for(int i=0; i<B; i++) {
        fprintf(stderr, "valid (%d):", i);
        for(auto e : valid[i]) cerr << " " << e;
        cerr << endl;
        fprintf(stderr, "valid_rev (%d):", i);
        for(auto e : valid_rev[i]) cerr << " " << e;
        cerr << endl;
    }
    */

    
    return 0;
}


Compiler output:
a.cc: In function 'int main()':
a.cc:426:50: error: invalid use of member function 'std::vector<_Tp, _Alloc>::size_type std::vector<_Tp, _Alloc>::size() const [with _Tp = int; _Alloc = std::allocator<int>; size_type = long unsigned int]' (did you forget the '()' ?)
  426 |         for(int j=0; j<B; j++) ok &= (cand[i][j].size > 0);
      |                                                      ()