//includes
#include<iostream>
#include<vector>
#include<set>
#include<tuple>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<map>
#include<queue>
#include<iomanip>
#include<numeric>
#include<assert.h>
#include<cstring>
#include<unordered_map>
#include<bitset>

//macros and consts
#define REP(i, n) for(int i = 0; i < (int)(n); i++)
#define all(a) (a).begin(),(a).end()
#define FOR(i,a,b) for(int i = (a); i < (b); i++)
#define FORE(i,a) for(auto &i : a)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define accm accumulate
#define Fi first
#define Se second
#define INF 1e9
#define llINF (1LL<<60)
#define mINF -1e9
#define mllINF -(1LL<<60)
#define endl "\n"
#define CONT continue
#define BRK break
#define modulo(n, m) (((n)%(m)+(m))%m)

//shorter types
using namespace std;
using ll = long long;
using vi = std::vector<int>;
using vc = std::vector<char>;
using vll = std::vector<long long>;
using vs = std::vector<string>;
using Mi = map<int,int>;
using Mll = map<ll,ll>;
using UMi = unordered_map<int,int>;
using UMll = unordered_map<ll,ll>;
using Pi = pair<int,int>;
using Pll = pair<ll,ll>;
using vPi = vector<Pi>;
using vPll = vector<Pll>;
using vvi = vector<vector<int>>;
using vvll = vector<vector<ll>>;
using vvc = vector<vector<char>>;
using vvs = vector<vector<string>>;
using pqgi = priority_queue<int,vector<int>,greater<int>>;
using pqsi = priority_queue<int,vector<int>,less<int>>;
using pqgll = priority_queue<int,vector<int>,greater<int>>;
using pssll = priority_queue<int,vector<int>,less<int>>;
template<class T>
using vec = vector<T>;
#define int long long

struct RollingHash{
	static const int base1 = 1007, base2 = 2009;
	static const int mod1 = 1000000007, mod2 = 1000000009;
	vector<int> hash1,hash2,power1,power2;

	RollingHash(const vector<int> &S){
		int n = (int)S.size();
		hash1.assign(n + 1,0);
		hash2.assign(n + 1,0);
		power1.assign(n + 1,1);
		power2.assign(n + 1,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;
			power1[i + 1] = (power1[i] * base1) % mod1;
			power2[i + 1] = (power2[i] * base2) % mod2;
		}
	}
	inline pair<int,int> get(int l,int r) const{
		int res1 = hash1[r] - hash1[l] * power1[r - l] % mod1;
		if(res1 < 0) res1 += mod1;
		int res2 = hash2[r] - hash2[l] * power2[r-l] % mod2;
		if(res2 < 0) res2 += mod2;
		return {res1,res2};
	}
	inline int getLCP(int a,int b) const{
		int len = min((int)hash1.size() - a, (int)hash1.size() - 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;
	}
	inline int getLCP(const RollingHash &T, int a, int b) const{
        int len = min((int)hash1.size()-a, (int)hash1.size()-b);
        int low = 0, high = len;
        while (high - low > 1) {
            int mid = (low + high) >> 1;
            if (get(a, a+mid) != T.get(b, b+mid)) high = mid;
            else low = mid;
        }
        return low;
	}
};
//here begins your code
signed main(){
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  int N;
  cin >> N;
  vector<int> a,b,da,db;
  a.resize(N);
  b.resize(N);
  for(int i = 0 ; i < N ; i++){
  	cin >> a[i];
  }
  for(int i = 0 ; i < N ; i++){
  	cin >> b[i];
  }

  da.resize(2*N);
  db.resize(2*N);
  for(int i = 0 ; i < 2 * N ; i++){
  	int j = i % N;
  	int k = ( i + 1 ) % N;
  	da[i] = a[j] ^ a[k];
  	db[i] = b[j] ^ b[k];
  }
  RollingHash A(da), B(db);
  for(int k = 0 ; k < N ; k++){
  	int len = A.getLCP(B,k,0);
  	if(len >= N){
  		cout << k << " " << (a[k] ^ b[0]) << endl;
  	}
  }
  //check types
  //do not eb if you resize
  //resize before you access by idx
  return 0;
} 

Measured memory_bytes: 37888