Problem:
Score : 600 points

Problem Statement

Given are two sequences a=\{a_0,\ldots,a_{N-1}\} and b=\{b_0,\ldots,b_{N-1}\} of N non-negative integers each.

Snuke will choose an integer k such that 0 \leq k < N and an integer x not less than 0, to make a new sequence of length N, a'=\{a_0',\ldots,a_{N-1}'\}, as follows:

a_i'= a_{i+k \mod N}\ XOR \ x

Find all pairs (k,x) such that a' will be equal to b.

What is \mbox{ XOR }?

The XOR of integers A and B, A \mbox{ XOR } B, is defined as follows:

When A \mbox{ XOR } B is written in base two, the digit in the 2^k's place (k \geq 0) is 1 if either A or B, but not both, has 1 in the 2^k's place, and 0 otherwise.

For example, 3 \mbox{ XOR } 5 = 6. (In base two: 011 \mbox{ XOR } 101 = 110.)

Constraints

1 \leq N \leq 2 \times 10^5

0 \leq a_i,b_i < 2^{30}

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
a_0 a_1 ... a_{N-1}
b_0 b_1 ... b_{N-1}

Output

Print all pairs (k, x) such that a' and b will be equal, using one line for each pair, in ascending order of k (ascending order of x for pairs with the same k).

If there are no such pairs, the output should be empty.

Sample Input 1

3
0 2 1
1 2 3

Sample Output 1

1 3

If (k,x)=(1,3),

a_0'=(a_1\ XOR \ 3)=1

a_1'=(a_2\ XOR \ 3)=2

a_2'=(a_0\ XOR \ 3)=3

and we have a' = b.

Sample Input 2

5
0 0 0 0 0
2 2 2 2 2

Sample Output 2

0 2
1 2
2 2
3 2
4 2

Sample Input 3

6
0 1 3 7 6 4
1 5 4 6 2 3

Sample Output 3

2 2
5 5

Sample Input 4

2
1 2
0 0

Sample Output 4

No pairs may satisfy the condition.

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;

namespace ABC150F
{
    class Program
    {
        static void Main(string[] args)
        {
            var N = int.Parse(Console.ReadLine());
            int[] a = ReadInt();
            int[] b = ReadInt();

            //差分列の作成
            int[] adiv = new int[N];
            int[] bdiv = new int[N];
            for (int i = 0; i < N; i++)
            {
                adiv[i] = a[(i + 1) % N] ^ a[i];
                bdiv[i] = b[(i + 1) % N] ^ b[i];
            }

            //長くする
            int[] along = new int[2 * N];
            Array.Copy(adiv, along, N);
            Array.Copy(adiv, 0, along, N, N);

            //dをずらしてマッチする部分を探す。
            List<int> k = new List<int>();
            List<int> x = new List<int>();
            RollingHash rh1 = new RollingHash(along);
            RollingHash rh2 = new RollingHash(bdiv);
            var hash = rh2.Hash();
            for (int i = 0; i < N; i++)
            {
                bool ok = false;

                //これだと遅いはず。
                //for (int w = 0; w < N; w++)
                //{
                //    if (along[i + w] != bdiv[w]) ok = false;
                //}
                var hash1 = rh1.Get(i, i + N);
                if (hash[0] == hash1[0] && hash[1] == hash1[1]) ok = true;

                if (ok)
                {
                    k.Add(i);
                    x.Add(a[i] ^ b[0]);
                }
            }

            //出力
            if (k.Count > 0)
            {
                for (int i = 0; i < k.Count; i++)
                {
                    Console.WriteLine(k[i] + " " + x[i]);
                }
            }
            else Console.WriteLine();
            Console.ReadKey();
        }

        static int[] ReadInt()
        {
            int[] ret = Console.ReadLine().Split().Select(int.Parse).ToArray();
            return ret;
        }
        static long[] ReadLong()
        {
            long[] ret = Console.ReadLine().Split().Select(long.Parse).ToArray();
            return ret;
        }
    }

    /// <summary>
    /// ローリングハッシュ安全バージョン
    /// </summary>
    class RollingHash
    {
        const long base1 = 1009;
        const long base2 = 2009;
        const long mod1 = 1000000007;
        const long mod2 = 1000000009;
        long[] hash1, hash2, pow1, pow2;

        public RollingHash(int[] S)
        {
            int n = S.Length;
            hash1 = new long[n + 1];
            hash2 = new long[n + 1];
            pow1 = new long[n + 1];
            pow2 = new long[n + 1];
            pow1[0] = 1;
            pow2[0] = 1;

            for (int i = 0; i < n; ++i)
            {
                hash1[i + 1] = (hash1[i] * base1 + S[i]) % mod1;
                hash2[i + 1] = (hash2[i] * base2 + S[i]) % mod2;
                pow1[i + 1] = (pow1[i] * base1) % mod1;
                pow2[i + 1] = (pow2[i] * base2) % mod2;
            }
        }

        /**
         * S の [l, r) のハッシュ値を返す
         * O(1)
         */
        public long[] Get(int l, int r)
        {
            long res1 = hash1[r] - hash1[l] * pow1[r - l] % mod1;
            if (res1 < 0) res1 += mod1;
            long res2 = hash2[r] - hash2[l] * pow2[r - l] % mod2;
            if (res2 < 0) res2 += mod2;
            return new long[] { res1, res2 };
        }

        /**
         * S のハッシュ値を返す
         * O(1)
         */
        public long[] Hash()
        {
            return Get(0, hash1.Length - 1);
        }

        /**
         * LCP (Longest Common Prefix)
         * O( log N )
         */
        public int GetLCP(int a, int b)
        {
            int len = Math.Min(hash1.Length - a, hash1.Length - b);
            int low = 0, high = len;
            while (high - low > 1)
            {
                int mid = (low + high) >> 1;
                if (Get(a, a + mid) != Get(b, b + mid)) high = mid;
                else low = mid;
            }
            return low;
        }

        /**
         * hash h1 と 長さ h2_len の文字列の hash h2 を結合
         */
        public long[] Concat(long[] h1, long[] h2, int h2_len)
        {
            return new long[] { (h1[0] * pow1[h2_len] + h2[0]) % mod1, (h1[1] * pow2[h2_len] + h2[1]) % mod2 };
        }
    }
}