#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <vector>
#include <string>
#include <iostream>
#include <cassert>
#include <algorithm>

using namespace std;

#define foreach(e,x) for(__typeof((x).begin()) e=(x).begin(); e!=(x).end(); ++e)

const int N = 100000 + 10;
const int MOD = 1e9 + 7;

int n;
long long x[N], y[N];
int tox[N];
long long c[N], d[N];
int fx[40], fy[40];
vector<pair<int ,int> > vec0;
vector<pair<int ,int> > vec1;

long long readInt()
{
	int x;
	scanf("%d", &x);
	return x;
}

void solve()
{
	cin >> n;
	memset(fx, -1, sizeof fx);
	memset(tox, -1, sizeof tox);
	for(int i = 0; i < n; ++ i) {
		x[i] = readInt();
		c[i] = x[i];
		for(int j = 31; j >= 0; -- j) {
			if (x[i] >> j & 1) {
				if (fx[j] >= 0) {
					x[i] ^= x[fx[j]];
					vec0.push_back(make_pair(i, fx[j]));
				} else {
					fx[j] = i;
					tox[i] = j;
				}
			} else {
			}
		}
	}

	memset(fy, -1, sizeof fy);
	for(int i = 0; i < n; ++ i) {
		y[i] = readInt();
		d[i] = y[i];
		for(int j = 31; j >= 0; -- j) {
			if (y[i] >> j & 1) {
				if (fy[j] >= 0) {
					y[i] ^= y[fy[j]];
					vec1.push_back(make_pair(i, fy[j]));
				} else {
					fy[j] = i;
				}
			} else {
			}
		}
	}

	for(int j = 31; j >= 0; -- j) {
		if (fy[j] >= 0) {
			if (fx[j] < 0) {
				cout << "-1" << endl;
				return;
			}
			if (fx[j] != fy[j]) {
				swap(x[fx[j]], x[fy[j]]);
				swap(tox[fx[j]], tox[fy[j]]);
				vec0.push_back(make_pair(fx[j], fy[j]));
				vec0.push_back(make_pair(fy[j], fx[j]));
				vec0.push_back(make_pair(fx[j], fy[j]));
				if (tox[fx[j]] >= 0) {
					fx[tox[fx[j]]] = fx[j];
				}
				if (tox[fy[j]] >= 0) {
					fx[tox[fy[j]]] = fy[j];
				}
			}
			for(int k = j - 1; k >= 0; -- k) {
				if ((x[fx[j]] >> k & 1) ^ (y[fx[j]] >> k & 1)) {
					if (fx[k] < 0) {
						cout << "-1" << endl;
						return;
					}
					x[fx[j]] ^= x[fx[k]];
					vec0.push_back(make_pair(fx[j], fx[k]));
				}
			}
		} else {
			if (fx[j] >= 0) {
				x[fx[j]] = 0;
				vec0.push_back(make_pair(fx[j], fx[j]));
			}
		}
	}
	for(int i = (int)vec1.size() - 1; i >= 0; -- i) {
		vec0.push_back(vec1[i]);
	}
	for(int i = 0; i < vec0.size(); ++ i) {
		printf("%d %d\n", vec0[i].first + 1, vec0[i].second + 1);
		c[vec0[i].first] ^= c[vec0[i].second];
	}
	for(int i = 0; i < n; ++ i) {
		assert(c[i] == d[i]);
	}
}

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


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())
#define mP make_pair
#define pB push_back
#define X first
#define Y second

int getHighestBit(int a) {
	for (int i = 31; i >= 0; i--) {
		if (a >> i & 1) {
			return i;
		}
	}
	return -1;
}

vector <int> spaceVector(vector <int> a, vector <pair <int, int> > &operation) {
	int n = sz(a);
	int higehstBit = 32;
	int start = 0;

	while (start < n) {
		int ind = start;
		int maxi = a[start];
		for (int j = start + 1; j < n; j++) {
			if (maxi < a[j]) {
				maxi = a[j];
				ind = j;
			}
		}
		if (ind != start) {
			swap(a[ind], a[start]);
			operation.pB(mP(ind, start));
			operation.pB(mP(start, ind));
			operation.pB(mP(ind, start));
		}

		higehstBit = getHighestBit(a[start]);
		if (higehstBit == -1) {
			break;
		}
		for (int j = start + 1; j < n; j++) {
			if (a[j] >> higehstBit & 1) {
				a[j] ^= a[start];
				operation.pB(mP(j, start));
			}
		}
		start++;
	}
	a.resize(start);
	return a;
}

int main() {
	vector <int> x, y;
	int n; cin >> n;
	x.resize(n);
	y.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
	}
	for (int i = 0; i < n; i++) {
		cin >> y[i];
	}

	vector <pair <int, int> > opGo, opRev;
	x = spaceVector(x, opGo);
	y = spaceVector(y, opRev);

	// for (int i = 0; i < sz(opGo); i++) {
	// 	cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
	// }
	// for (int i = sz(opRev) - 1; i >= 0; i--) {
	// 	cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
	// }
	// cout << "---" << endl;
	// for (int i = 0; i < sz(x); i++) {
	// 	cout << x[i] << ' ';
	// }
	// cout << endl;
	// for (int i = 0; i < sz(y); i++) {
	// 	cout << y[i] << ' ';
	// }
	// cout << endl;
	// cout << "---" << endl;

	bool can = true;
	if (sz(x) < sz(y)) {
		if (n > 1000) {
			while(true);
		}
		can = false;
	}
	else {
		int yIter = 0;
		int xIter = 0;
		int step = 0;

		while (can && yIter < sz(y)) {
			while (step < sz(x) && getHighestBit(x[step]) > getHighestBit(y[yIter])) {
				step++;
			}
			if (step >= sz(x) || getHighestBit(x[step]) != getHighestBit(y[yIter])) {
				can = false;
				break;
			}
			if (xIter != step) {
				swap(x[xIter], x[step]);
				opGo.pB(mP(xIter, step));
				opGo.pB(mP(step, xIter));
				opGo.pB(mP(xIter, step));
			}

			step++;
			int nextSteps = step;
			while (x[xIter] != y[yIter]) {
				int dif = x[xIter] ^ y[yIter];
				int higehstBit = getHighestBit(dif);
				while (nextSteps < sz(x) && higehstBit > getHighestBit(x[nextSteps])) {
					nextSteps++;
				}
				if (nextSteps >= sz(x) || higehstBit != getHighestBit(x[nextSteps])) {
					can = false;
					break;
				}
				x[xIter] ^= x[nextSteps];
				opGo.pB(mP(xIter, nextSteps));
			}
			xIter++; yIter++;
		}
	}
	// }
	if (!can) {
		cout << "-1" << endl;
	}
	else {
		for (int i = sz(y); i < sz(x); i++) {
			opGo.pB(mP(i, i));
		}
		cout << sz(opRev) + sz(opGo) << endl;
		reverse(opRev.begin(), opRev.end());
		for (int i = 0; i < sz(opGo); i++) {
			cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
		}
		for (int i = 0; i < sz(opRev); i++) {
			cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
		}
	}
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())
#define mP make_pair
#define pB push_back
#define X first
#define Y second

int getHighestBit(int a) {
	for (int i = 31; i >= 0; i--) {
		if (a >> i & 1) {
			return i;
		}
	}
	return -1;
}

vector <int> spaceVector(vector <int> a, vector <pair <int, int> > &operation) {
	int n = sz(a);
	int higehstBit = 32;
	int start = 0;

	while (start < n) {
		int ind = start;
		int maxi = a[start];
		for (int j = start + 1; j < n; j++) {
			if (maxi < a[j]) {
				maxi = a[j];
				ind = j;
			}
		}
		if (ind != start) {
			swap(a[ind], a[start]);
			operation.pB(mP(ind, start));
			operation.pB(mP(start, ind));
			operation.pB(mP(ind, start));
		}

		higehstBit = getHighestBit(a[start]);
		if (higehstBit == -1) {
			break;
		}
		for (int j = start + 1; j < n; j++) {
			if (a[j] >> higehstBit & 1) {
				a[j] ^= a[start];
				operation.pB(mP(j, start));
			}
		}
		start++;
	}
	a.resize(start);
	return a;
}

int main() {
	vector <int> x, y;
	int n; cin >> n;
	x.resize(n);
	y.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
	}
	for (int i = 0; i < n; i++) {
		cin >> y[i];
	}

	vector <pair <int, int> > opGo, opRev;
	x = spaceVector(x, opGo);
	y = spaceVector(y, opRev);

	// for (int i = 0; i < sz(opGo); i++) {
	// 	cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
	// }
	// for (int i = sz(opRev) - 1; i >= 0; i--) {
	// 	cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
	// }
	// cout << "---" << endl;
	// for (int i = 0; i < sz(x); i++) {
	// 	cout << x[i] << ' ';
	// }
	// cout << endl;
	// for (int i = 0; i < sz(y); i++) {
	// 	cout << y[i] << ' ';
	// }
	// cout << endl;
	// cout << "---" << endl;

	bool can = true;
	if (sz(x) < sz(y)) {
		if (n > 1000) {
			while(true);
		}
		can = false;
	}
	else {
		cout << "size of x: " << sz(x) << endl;
		cout << "size of y: " << sz(y) << endl;
		int yIter = 0;
		int xIter = 0;
		int step = 0;

		while (can && yIter < sz(y)) {
			while (step < sz(x) && getHighestBit(x[step]) > getHighestBit(y[yIter])) {
				step++;
			}
			if (step >= sz(x) || getHighestBit(x[step]) != getHighestBit(y[yIter])) {
				can = false;
				break;
			}
			if (xIter != step) {
				swap(x[xIter], x[step]);
				opGo.pB(mP(xIter, step));
				opGo.pB(mP(step, xIter));
				opGo.pB(mP(xIter, step));
			}

			step++;
			int nextSteps = step;
			while (x[xIter] != y[yIter]) {
				int dif = x[xIter] ^ y[yIter];
				int higehstBit = getHighestBit(dif);
				while (nextSteps < sz(x) && higehstBit > getHighestBit(x[nextSteps])) {
					nextSteps++;
				}
				if (nextSteps >= sz(x) || higehstBit != getHighestBit(x[nextSteps])) {
					can = false;
					break;
				}
				x[xIter] ^= x[nextSteps];
				opGo.pB(mP(xIter, nextSteps));
			}
			xIter++; yIter++;
		}
	}
	// }
	if (!can) {
		cout << "-1" << endl;
	}
	else {
		for (int i = sz(y); i < sz(x); i++) {
			opGo.pB(mP(i, i));
		}
		cout << sz(opRev) + sz(opGo) << endl;
		reverse(opRev.begin(), opRev.end());
		for (int i = 0; i < sz(opGo); i++) {
			cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
		}
		for (int i = 0; i < sz(opRev); i++) {
			cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
		}
	}
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())

vector <int> row[33];
int jadCol[10000 + 5];
vector <int> selected;
vector <int> y;
vector <int> x;
vector <pair <int, int> > operations;
int n;
int maxi;

// Xor equal the idx1 row by idx2 row
void xorEq(int idx1, int idx2) {
	for (int i = 0; i < n + 1; i++) {
		row[idx1][i] ^= row[idx2][i];
	}
}

// build the index idx of Ys with Xs
// return 0 if can't
int buildThis(int idx) {
	for (int i = 0; i < 33; i++) {
		row[i].clear();
	}
	for (int i = 0; i < n; i++) {
		jadCol[i] = -1;
	}

	// build rows
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < 33; j++) {
			row[j].push_back((x[i] >> j) & 1);
		}
	}
	for (int j = 0; j < 33; j++) {
		row[j].push_back((y[idx] >> j) & 1);
	}

	// gauss elimination
	int par = -1;
	int start = 0;
	for (int i = 0; i < n && start <= maxi; i++) {
		int cur = -1;
		for (int j = start; j < 33; j++) {
			if (row[j][i] != 0) {
				cur = j;
				break;
			}
		}

		if (cur != -1) {
			swap(row[start], row[cur]);
			jadCol[i] = par;
			par = i;
			start++;
			for (int j = start; j < 33; j++) {
				if (row[j][i] != 0) {
					xorEq(j, start - 1);
				}
			}
		}
	}

	vector <int> used;
	while (par != -1) {
		used.push_back(par);
		for (int i = start - 2; i >= 0; i--) {
			if (row[i][par] != 0) {
				xorEq(i, start - 1);
			}
		}
		start--;
		par = jadCol[par];
	}

	selected.clear();
	reverse(used.begin(), used.end());
	start = 0;
	int ans = 0;
	bool selfi = false;
	for (int i = 0; i < used.size(); i++) {
		if (row[used[i]][n] == 1) {
			ans ^= x[used[i]];
			selected.push_back(used[i]);
		}
	}

	if (ans == y[idx]) {
		return 1;
	}
	return 0;
}

void swapOperation(int idx1, int idx2) {
	operations.push_back(make_pair(idx1, idx2));
	operations.push_back(make_pair(idx2, idx1));
	operations.push_back(make_pair(idx1, idx2));
	swap(x[idx1], x[idx2]);
}

int highestOne(int a) {
	for (int i = 31; i >= 0; i--) {
		if ((a >> i) & 1) {
			return i;
		}
	}
	return 0;
}

int main() {
	cin >> n;
	x.resize(n);
	y.resize(n);
	maxi = -1;
	for (int i = 0; i < n; i++) {
		cin >> x[i];
		if (x[i] != 0) {
			maxi = max(maxi, highestOne(x[i]));
		}
	}
	char could = 1;
	for (int i = 0; i < n; i++) {
		cin >> y[i];
		if (y[i] == 0) {
			continue;
		}
		int can = buildThis(i);
		if (can == 0) {
			could = 0;
			break;
		}
		// cout << "can: " << can << endl;
		bool selfi = false;
		for (int j = 0; j < selected.size(); j++) {
			if (selected[j] == i) {
				selfi = true;
				break;
			}
		}
		int end = sz(selected);
		// cout << end << endl;
		if (!selfi) {
			int where = selected[sz(selected) - 1];
			if (where > i) {
				swapOperation(i, selected[sz(selected) - 1]);
				end--;
			}
			else {
				operations.push_back(make_pair(i, i));
				x[i] = 0;
			}
		}
		for (int j = 0; j < end; j++) {
			if (selected[j] != i) {
				operations.push_back(make_pair(i, selected[j]));
				x[i] ^= x[selected[j]];
			}
		}
	}

	if (could == 0) {
		cout << -1 << endl;
		return 0;
	}

	for (int i = 0; i < n; i++) {
		if (x[i] != 0 && y[i] == 0) {
			operations.push_back(make_pair(i, i));
		}
	}
	cout << operations.size() << endl;
	for (int i = 0; i < operations.size(); i++) {
		cout << operations[i].first + 1 << ' ' << operations[i].second + 1 << endl;
	}

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())
#define mP make_pair
#define pB push_back
#define X first
#define Y second

int getHighestBit(int a) {
	for (int i = 31; i >= 0; i--) {
		if (a >> i & 1) {
			return 1 << i;
		}
	}
	return 0;
}

vector <int> spaceVector(vector <int> a, vector <pair <int, int> > &operation) {
	int n = sz(a);
	int start = 0;

	while (start < n) {
		int ind = start;
		int maxi = a[start];
		for (int j = start + 1; j < n; j++) {
			if (maxi < a[j]) {
				maxi = a[j];
				ind = j;
			}
		}
		if (ind != start) {
			swap(a[ind], a[start]);
			operation.pB(mP(ind, start));
			operation.pB(mP(start, ind));
			operation.pB(mP(ind, start));
		}

		int higehstBit = getHighestBit(a[start]);
		if (higehstBit == 0) {
			break;
		}
		for (int j = start + 1; j < n; j++) {
			if ((a[j] & higehstBit) != 0) {
				a[j] ^= a[start];
				operation.pB(mP(j, start));
			}
		}
		start++;
	}
	a.resize(start);
	return a;
}

int main() {
	ios_base::sync_with_stdio(false);
	vector <int> x, y;
	int n; cin >> n;
	x.resize(n);
	y.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
	}
	for (int i = 0; i < n; i++) {
		cin >> y[i];
	}

	vector <pair <int, int> > opGo, opRev;
	x = spaceVector(x, opGo);
	y = spaceVector(y, opRev);

	bool can = true;
	if (sz(x) < sz(y)) {
		can = false;
	}
	else {
		int yIter = 0;
		int xIter = 0;
		int step = 0;

		while (can && yIter < sz(y)) {
			int higehstBit = getHighestBit(y[yIter]);
			while (step < sz(x) && getHighestBit(x[step]) > higehstBit) {
				step++;
			}
			if (step >= sz(x) || getHighestBit(x[step]) != higehstBit) {
				can = false;
				break;
			}
			if (xIter != step) {
				swap(x[xIter], x[step]);
				opGo.pB(mP(xIter, step));
				opGo.pB(mP(step, xIter));
				opGo.pB(mP(xIter, step));
			}

			step++;
			int nextSteps = step;
			while (x[xIter] != y[yIter]) {
				int dif = x[xIter] ^ y[yIter];
				higehstBit = getHighestBit(dif);
				while (nextSteps < sz(x) && getHighestBit(x[nextSteps]) > higehstBit) {
					nextSteps++;
				}
				if (nextSteps >= sz(x) || getHighestBit(x[nextSteps]) != higehstBit) {
					can = false;
					break;
				}
				x[xIter] ^= x[nextSteps];
				opGo.pB(mP(xIter, nextSteps));
			}
			xIter++; yIter++;
		}
	}
	if (!can) {
		cout << "-1" << endl;
	}
	else {
		for (int i = sz(y); i < sz(x); i++) {
			opGo.pB(mP(i, i));
		}
		cout << sz(opRev) + sz(opGo) << endl;
		reverse(opRev.begin(), opRev.end());
		for (int i = 0; i < sz(opGo); i++) {
			cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
		}
		for (int i = 0; i < sz(opRev); i++) {
			cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
		}
	}
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())

vector <int> row[33];
int jadCol[10000 + 5];
vector <int> selected;
vector <int> y;
vector <int> x;
vector <pair <int, int> > operations;
int n;
int maxi;

// Xor equal the idx1 row by idx2 row
void xorEq(int idx1, int idx2) {
	for (int i = 0; i < n + 1; i++) {
		row[idx1][i] ^= row[idx2][i];
	}
}

void initial() {
	// build rows
	for (int j = 0; j < 33; j++) {
		row[j].resize(n);
		for (int i = 0; i < n; i++) {
			row[j][i] = (x[i] >> j) & 1;
		}
	}
}

void updateY(int idx) {
	for (int i = 0; i < 33; i++) {
		row[i].push_back((y[idx] >> i) & 1);
	}
}

// void updateX(int idx, int val) {
// 	for (int i = 0; i < 33; i++) {
// 		row[i][idx] = (val >> i) & 1;
// 	}
// }

// build the index idx of Ys with Xs
// return 0 if can't
int buildThis(int idx) {
	initial();
	updateY(idx);

	// gauss elimination
	int par = -1;
	int start = 0;
	for (int i = 0; i < n && start <= maxi; i++) {
		int cur = -1;
		for (int j = start; j < 33; j++) {
			if (row[j][i] != 0) {
				cur = j;
				break;
			}
		}

		if (cur != -1) {
			swap(row[start], row[cur]);
			jadCol[i] = par;
			par = i;
			start++;
			for (int j = start; j < 33; j++) {
				if (row[j][i] != 0) {
					xorEq(j, start - 1);
				}
			}
		}
	}

	vector <int> used;
	while (par != -1) {
		used.push_back(par);
		for (int i = start - 2; i >= 0; i--) {
			if (row[i][par] != 0) {
				xorEq(i, start - 1);
			}
		}
		start--;
		int bef = par;
		par = jadCol[par];
		if (bef != -1) {
			jadCol[bef] = -1;
		}
	}

	selected.clear();
	reverse(used.begin(), used.end());
	start = 0;
	int ans = 0;
	bool selfi = false;
	for (int i = 0; i < used.size(); i++) {
		if (row[used[i]][n] == 1) {
			ans ^= x[used[i]];
			selected.push_back(used[i]);
		}
	}

	if (ans == y[idx]) {
		return 1;
	}
	return 0;
}

void swapOperation(int idx1, int idx2) {
	operations.push_back(make_pair(idx1, idx2));
	operations.push_back(make_pair(idx2, idx1));
	operations.push_back(make_pair(idx1, idx2));
	swap(x[idx1], x[idx2]);
	// updateX(idx1, x[idx1]);
	// updateX(idx2, x[idx2]);
}

int highestOne(int a) {
	for (int i = 32; i >= 0; i--) {
		if ((a >> i) & 1) {
			return i;
		}
	}
	return 0;
}

int main() {
	cin >> n;
	x.resize(n);
	y.resize(n);
	maxi = -1;
	for (int i = 0; i < n; i++) {
		cin >> x[i];
		if (x[i] != 0) {
			maxi = max(maxi, highestOne(x[i]));
		}
	}
	initial();

	char could = 1;
	for (int i = 0; i < n; i++) {
		cin >> y[i];
		if (y[i] == 0) {
			continue;
		}
		int can = buildThis(i);
		if (can == 0) {
			could = 0;
			break;
		}
		// cout << "can: " << can << endl;
		bool selfi = false;
		for (int j = 0; j < selected.size(); j++) {
			if (selected[j] == i) {
				selfi = true;
				break;
			}
		}
		int end = sz(selected);
		// cout << end << endl;
		if (!selfi) {
			int where = selected[sz(selected) - 1];
			if (where > i) {
				swapOperation(i, selected[sz(selected) - 1]);
				end--;
			}
			else {
				operations.push_back(make_pair(i, i));
				x[i] = 0;
			}
		}
		for (int j = 0; j < end; j++) {
			if (selected[j] != i) {
				operations.push_back(make_pair(i, selected[j]));
				x[i] ^= x[selected[j]];
			}
		}
		// updateX(i, x[i]);
		// cout << "---" << endl;
		// for (int i = 0; i < 7; i++) {
		// 	for (int j = 0; j < n + 1; j++) {
		// 		cout << row[i][j] << ' ';
		// 	}
		// 	cout << endl;
		// }
		// cout << "---" << endl;
	}

	if (could == 0) {
		cout << -1 << endl;
		return 0;
	}

	for (int i = 0; i < n; i++) {
		if (x[i] != 0 && y[i] == 0) {
			operations.push_back(make_pair(i, i));
		}
	}
	cout << operations.size() << endl;
	for (int i = 0; i < operations.size(); i++) {
		cout << operations[i].first + 1 << ' ' << operations[i].second + 1 << endl;
	}

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())
#define mP make_pair
#define pB push_back
#define X first
#define Y second

int getHighestBit(int a) {
	for (int i = 31; i >= 0; i--) {
		if (a >> i & 1) {
			return i;
		}
	}
	return -1;
}

vector <int> spaceVector(vector <int> a, vector <pair <int, int> > &operation) {
	int n = sz(a);
	int higehstBit = 31;
	int start = 0;

	while (start < n) {
		int ind = start;
		int maxi = a[start];
		for (int j = start + 1; j < n; j++) {
			if (maxi < a[j]) {
				maxi = a[j];
				ind = j;
			}
		}
		if (ind != start) {
			swap(a[ind], a[start]);
			operation.pB(mP(ind, start));
			operation.pB(mP(start, ind));
			operation.pB(mP(ind, start));
		}

		higehstBit = getHighestBit(a[start]);
		if (higehstBit == -1) {
			break;
		}
		for (int j = start + 1; j < n; j++) {
			if (a[j] >> higehstBit & 1) {
				a[j] ^= a[start];
				operation.pB(mP(j, start));
			}
		}
		start++;
	}
	a.resize(start);
	return a;
}

int main() {
	vector <int> x, y;
	int n; cin >> n;
	x.resize(n);
	y.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
	}
	for (int i = 0; i < n; i++) {
		cin >> y[i];
	}

	vector <pair <int, int> > opGo, opRev;
	x = spaceVector(x, opGo);
	y = spaceVector(y, opRev);

	// for (int i = 0; i < sz(opGo); i++) {
	// 	cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
	// }
	// for (int i = sz(opRev) - 1; i >= 0; i--) {
	// 	cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
	// }
	// cout << "---" << endl;
	// for (int i = 0; i < sz(x); i++) {
	// 	cout << x[i] << ' ';
	// }
	// cout << endl;
	// for (int i = 0; i < sz(y); i++) {
	// 	cout << y[i] << ' ';
	// }
	// cout << endl;
	// cout << "---" << endl;

	bool can = true;
	if (sz(x) < sz(y)) {
		can = false;
	}
	else {
		int yIter = 0;
		int xIter = 0;
		int step = 0;

		while (can && yIter < sz(y)) {
			while (step < sz(x) && getHighestBit(x[step]) > getHighestBit(y[yIter])) {
				step++;
			}
			if (step >= sz(x) || getHighestBit(x[step]) != getHighestBit(y[yIter])) {
				can = false;
				break;
			}
			if (xIter != step) {
				swap(x[xIter], x[step]);
				opGo.pB(mP(xIter, step));
				opGo.pB(mP(step, xIter));
				opGo.pB(mP(xIter, step));
			}

			step++;
			int nextSteps = step;
			while (x[xIter] != y[yIter]) {
				int dif = x[xIter] ^ y[yIter];
				int higehstBit = getHighestBit(dif);
				while (nextSteps < sz(x) && higehstBit > getHighestBit(x[nextSteps])) {
					nextSteps++;
				}
				if (nextSteps >= sz(x) || higehstBit != getHighestBit(x[nextSteps])) {
					can = false;
					break;
				}
				x[xIter] ^= x[nextSteps];
				opGo.pB(mP(xIter, nextSteps));
			}
			xIter++; yIter++;
		}
	}
	// }
	if (!can) {
		cout << "-1" << endl;
	}
	else {
		for (int i = sz(y); i < sz(x); i++) {
			opGo.pB(mP(i, i));
		}
		cout << sz(opRev) + sz(opGo) << endl;
		reverse(opRev.begin(), opRev.end());
		for (int i = 0; i < sz(opGo); i++) {
			cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
		}
		for (int i = 0; i < sz(opRev); i++) {
			cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
		}
		cout << endl;
	}
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())

vector <int> row[33];
int jadCol[10000 + 5];
vector <int> selected;
vector <int> y;
vector <int> x;
vector <pair <int, int> > operations;
int n;

// Xor equal the idx1 row by idx2 row
void xorEq(int idx1, int idx2) {
	for (int i = 0; i < n + 1; i++) {
		row[idx1][i] ^= row[idx2][i];
	}
}

// build the index idx of Ys with Xs
// return 0 if can't
int buildThis(int idx) {
	for (int i = 0; i < 33; i++) {
		row[i].clear();
	}
	for (int i = 0; i < n; i++) {
		jadCol[i] = -1;
	}

	// build rows
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < 33; j++) {
			row[j].push_back((x[i] >> j) & 1);
		}
	}
	for (int j = 0; j < 33; j++) {
		row[j].push_back((y[idx] >> j) & 1);
	}

	// gauss elimination
	int par = -1;
	int start = 0;
	for (int i = 0; i < n; i++) {
		int cur = -1;
		for (int j = start; j < 33; j++) {
			if (row[j][i] != 0) {
				cur = j;
				break;
			}
		}

		if (cur != -1) {
			swap(row[start], row[cur]);
			jadCol[i] = par;
			par = i;
			start++;
			for (int j = start; j < 33; j++) {
				if (row[j][i] != 0) {
					xorEq(j, start - 1);
				}
			}
		}
	}

	vector <int> used;
	while (par != -1) {
		used.push_back(par);
		for (int i = start - 2; i >= 0; i--) {
			if (row[i][par] != 0) {
				xorEq(i, start - 1);
			}
		}
		start--;
		par = jadCol[par];
	}

	selected.clear();
	reverse(used.begin(), used.end());
	start = 0;
	int ans = 0;
	bool selfi = false;
	for (int i = 0; i < used.size(); i++) {
		if (row[used[i]][n] == 1) {
			ans ^= x[used[i]];
			selected.push_back(used[i]);
		}
	}

	if (ans == y[idx]) {
		return 1;
	}
	return 0;
}

void swapOperation(int idx1, int idx2) {
	operations.push_back(make_pair(idx1, idx2));
	operations.push_back(make_pair(idx2, idx1));
	operations.push_back(make_pair(idx1, idx2));
	swap(x[idx1], x[idx2]);
}

int main() {
	cin >> n;
	x.resize(n);
	y.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
	}
	char could = 1;
	for (int i = 0; i < n; i++) {
		cin >> y[i];
		int can = buildThis(i);
		if (can == 0) {
			could = 0;
			break;
		}

		bool selfi = false;
		for (int j = 0; j < selected.size(); j++) {
			if (selected[j] == i) {
				selfi = true;
				break;
			}
		}
		int end = sz(selected);
		if (!selfi) {
			int where = selected[sz(selected) - 1];
			if (where > i) {
				swapOperation(i, selected[sz(selected) - 1]);
				end--;
			}
			else {
				operations.push_back(make_pair(i, i));
				x[i] = 0;
			}
		}
		for (int j = 0; j < end; j++) {
			if (selected[j] != i) {
				operations.push_back(make_pair(i, selected[j]));
				x[i] ^= x[selected[j]];
			}
		}
	}

	if (could == 0) {
		cout << -1 << endl;
		return 0;
	}

	cout << operations.size() << endl;
	for (int i = 0; i < operations.size(); i++) {
		cout << operations[i].first + 1 << ' ' << operations[i].second + 1 << endl;
	}

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())
#define mP make_pair
#define pB push_back
#define X first
#define Y second

int getHighestBit(int a) {
	for (int i = 31; i >= 0; i--) {
		if (a >> i & 1) {
			return 1 << i;
		}
	}
	return 0;
}

vector <int> spaceVector(vector <int> a, vector <pair <int, int> > &operation) {
	int n = sz(a);
	int start = 0;

	while (start < n) {
		int ind = start;
		int maxi = a[start];
		for (int j = start + 1; j < n; j++) {
			if (maxi < a[j]) {
				maxi = a[j];
				ind = j;
			}
		}
		if (ind != start) {
			swap(a[ind], a[start]);
			operation.pB(mP(ind, start));
			operation.pB(mP(start, ind));
			operation.pB(mP(ind, start));
		}

		int higehstBit = getHighestBit(a[start]);
		if (higehstBit == 0) {
			break;
		}
		for (int j = start + 1; j < n; j++) {
			if ((a[j] & higehstBit) != 0) {
				a[j] ^= a[start];
				operation.pB(mP(j, start));
			}
		}
		start++;
	}
	a.resize(start);
	return a;
}

int main() {
	vector <int> x, y;
	int n; cin >> n;
	x.resize(n);
	y.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
	}
	for (int i = 0; i < n; i++) {
		cin >> y[i];
	}

	vector <pair <int, int> > opGo, opRev;
	x = spaceVector(x, opGo);
	y = spaceVector(y, opRev);

	// for (int i = 0; i < sz(opGo); i++) {
	// 	cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
	// }
	// for (int i = sz(opRev) - 1; i >= 0; i--) {
	// 	cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
	// }
	// cout << "---" << endl;
	// for (int i = 0; i < sz(x); i++) {
	// 	cout << x[i] << ' ';
	// }
	// cout << endl;
	// for (int i = 0; i < sz(y); i++) {
	// 	cout << y[i] << ' ';
	// }
	// cout << endl;
	// cout << "---" << endl;

	bool can = true;
	if (sz(x) < sz(y)) {
		can = false;
	}
	else {
		// cout << "size of x: " << sz(x) << endl;
		// cout << "size of y: " << sz(y) << endl;
		int yIter = 0;
		int xIter = 0;
		int step = 0;

		while (can && yIter < sz(y)) {
			int higehstBit = getHighestBit(y[yIter]);
			while (step < sz(x) && getHighestBit(x[step]) > higehstBit) {
				step++;
			}
			if (step >= sz(x) || getHighestBit(x[step]) != higehstBit) {
				can = false;
				break;
			}
			if (xIter != step) {
				swap(x[xIter], x[step]);
				opGo.pB(mP(xIter, step));
				opGo.pB(mP(step, xIter));
				opGo.pB(mP(xIter, step));
			}

			step++;
			int nextSteps = step;
			while (x[xIter] != y[yIter]) {
				int dif = x[xIter] ^ y[yIter];
				higehstBit = getHighestBit(dif);
				while (nextSteps < sz(x) && getHighestBit(x[nextSteps]) > higehstBit) {
					nextSteps++;
				}
				if (nextSteps >= sz(x) || getHighestBit(x[nextSteps]) != higehstBit) {
					can = false;
					break;
				}
				x[xIter] ^= x[nextSteps];
				opGo.pB(mP(xIter, nextSteps));
			}
			xIter++; yIter++;
		}
	}
	// }
	if (!can) {
		cout << "-1" << endl;
	}
	else {
		for (int i = sz(y); i < sz(x); i++) {
			opGo.pB(mP(i, i));
		}
		cout << sz(opRev) + sz(opGo) << endl;
		reverse(opRev.begin(), opRev.end());
		for (int i = 0; i < sz(opGo); i++) {
			cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
		}
		for (int i = 0; i < sz(opRev); i++) {
			cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
		}
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())
#define X first
#define Y second
#define mP make_pair
#define pB push_back
#define pii pair <int, int>

int getHighestOne(int a) {
	for (int i = 31; i >= 0; i--) {
		if (((1 << i) & a) != 0) {
			return 1 << i;
		}
	}
	return 0;
}

void xorOperation(vector <int> &a, int idx1, int idx2, vector <pii> &operation) {
	a[idx1] ^= a[idx2];
	operation.pB(mP(idx1, idx2));
}

void swapOperation(vector <int> &a, int idx1, int idx2, vector <pii> &operation) {
	xorOperation(a, idx1, idx2, operation);
	xorOperation(a, idx2, idx1, operation);
	xorOperation(a, idx1, idx2, operation);
}

vector <int> spaceVector(vector <int> a, vector <pii> &operation) {
	int start = 0;
	while (start < sz(a)) {
		int idx = -1;
		for (int i = start; i < sz(a); i++) {
			if (idx == -1 || a[idx] < a[i]) {
				idx = i;
			}
		}
		if (a[idx] == 0) {
			break;
		}
		if (idx != start) {
			swapOperation(a, idx, start, operation);
		}
		int highestOne = getHighestOne(a[start]);
		for (int i = start + 1; i < sz(a); i++) {
			if (highestOne & a[i]) {
				xorOperation(a, i, start, operation);
			}
		}
		start++;
	}

	a.resize(start);
	return a;
}

int main() {
	int n; scanf("%d", &n);
	vector <int> x(n), y(n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &x[i]);
	}
	for (int i = 0; i < n; i++) {
		scanf("%d", &y[i]);
	}

	vector <pii> opForward, opBackward;
	x = spaceVector(x, opForward);
	y = spaceVector(y, opBackward);

	// for (int i = 0; i < sz(x); i++) {
	// 	cout << x[i] << ' ';
	// }
	// cout << endl;
	// for (int i = 0; i < sz(y); i++) {
	// 	cout << y[i] << ' ';
	// }
	// cout << endl;

	bool can = true;
	if (sz(x) < sz(y)) {
		can = false;
	}
	else {
		int yIter = 0;
		int xIter = 0;
		int pioneer = 0;

		while (can && yIter < sz(y)) {
			int highestOne = getHighestOne(y[yIter]);
			while (pioneer < sz(x) && highestOne < getHighestOne(x[pioneer])) {
				pioneer ++;
			}
			if (pioneer >= sz(x) || highestOne != getHighestOne(x[pioneer])) {
				can = false;
				break;
			}
			// cout << ":: " << xIter << ' ' << pioneer << endl;
			if (xIter != pioneer) {
				// cout << "-----" << endl;
				// cout << x[xIter] << ' ' << x[pioneer] << endl;
				swapOperation(x, xIter, pioneer, opForward);
				// cout << x[xIter] << ' ' << x[pioneer] << endl;
				// cout << "-----" << endl;
			}
			pioneer++;
			int nextPioneer = pioneer;
			while (x[xIter] != y[yIter]) {
				int diff = x[xIter] ^ y[yIter];
				highestOne = getHighestOne(diff);
				while (nextPioneer < sz(x) && highestOne < getHighestOne(x[nextPioneer])) {
					nextPioneer++;
				}
				if (nextPioneer >= sz(x) || highestOne != getHighestOne(x[nextPioneer])) {
					can = false;
					break;
				}

				xorOperation(x, xIter, nextPioneer, opForward);
			}

			xIter++; yIter++;
		}
	}
	if (can) {
		for (int i = sz(y); i < sz(x); i++) {
			xorOperation(x, i, i, opForward);
		}
		printf("%d\n", sz(opBackward) + sz(opForward));
		for (int i = 0; i < sz(opForward); i++) {
			printf("%d %d\n", opForward[i].X + 1, opForward[i].Y + 1);
		}
		for (int i = sz(opBackward) - 1; i >= 0; i--) {
			printf("%d %d\n", opBackward[i].X + 1, opBackward[i].Y + 1);
		}
	}
	else {
		printf("-1\n");
	}

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())
#define mP make_pair
#define pB push_back
#define X first
#define Y second

int getHighestBit(int a) {
	for (int i = 32; i >= 0; i--) {
		if (a >> i & 1) {
			return i;
		}
	}
	return -1;
}

vector <int> spaceVector(vector <int> a, vector <pair <int, int> > &operation) {
	int n = sz(a);
	int higehstBit = 32;
	int start = 0;

	while (start < n) {
		int ind = start;
		int maxi = a[start];
		for (int j = start + 1; j < n; j++) {
			if (maxi < a[j]) {
				maxi = a[j];
				ind = j;
			}
		}
		if (ind != start) {
			swap(a[ind], a[start]);
			operation.pB(mP(ind, start));
			operation.pB(mP(start, ind));
			operation.pB(mP(ind, start));
		}

		higehstBit = getHighestBit(a[start]);
		if (higehstBit == -1) {
			break;
		}
		for (int j = start + 1; j < n; j++) {
			if (a[j] >> higehstBit & 1) {
				a[j] ^= a[start];
				operation.pB(mP(j, start));
			}
		}
		start++;
	}
	a.resize(start);
	return a;
}

int main() {
	vector <int> x, y;
	int n; cin >> n;
	x.resize(n);
	y.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
	}
	for (int i = 0; i < n; i++) {
		cin >> y[i];
	}

	vector <pair <int, int> > opGo, opRev;
	x = spaceVector(x, opGo);
	y = spaceVector(y, opRev);

	// for (int i = 0; i < sz(opGo); i++) {
	// 	cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
	// }
	// for (int i = sz(opRev) - 1; i >= 0; i--) {
	// 	cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
	// }
	// cout << "---" << endl;
	// for (int i = 0; i < sz(x); i++) {
	// 	cout << x[i] << ' ';
	// }
	// cout << endl;
	// for (int i = 0; i < sz(y); i++) {
	// 	cout << y[i] << ' ';
	// }
	// cout << endl;
	// cout << "---" << endl;

	bool can = true;
	if (sz(x) < sz(y)) {
		can = false;
	}
	else {
		int yIter = 0;
		int xIter = 0;
		int step = 0;

		while (can && yIter < sz(y)) {
			while (step < sz(x) && getHighestBit(x[step]) > getHighestBit(y[yIter])) {
				step++;
			}
			if (step >= sz(x) || getHighestBit(x[step]) != getHighestBit(y[yIter])) {
				can = false;
				break;
			}
			if (xIter != step) {
				swap(x[xIter], x[step]);
				opGo.pB(mP(xIter, step));
				opGo.pB(mP(step, xIter));
				opGo.pB(mP(xIter, step));
			}

			step++;
			int nextSteps = step;
			while (x[xIter] != y[yIter]) {
				int dif = x[xIter] ^ y[yIter];
				int higehstBit = getHighestBit(dif);
				while (nextSteps < sz(x) && higehstBit > getHighestBit(x[nextSteps])) {
					nextSteps++;
				}
				if (nextSteps >= sz(x) || higehstBit != getHighestBit(x[nextSteps])) {
					can = false;
					break;
				}
				x[xIter] ^= x[nextSteps];
				opGo.pB(mP(xIter, nextSteps));
			}
			xIter++; yIter++;
		}
	}
	// }
	if (!can) {
		cout << "-1" << endl;
	}
	else {
		for (int i = sz(y); i < sz(x); i++) {
			opGo.pB(mP(i, i));
		}
		cout << sz(opRev) + sz(opGo) << endl;
		reverse(opRev.begin(), opRev.end());
		for (int i = 0; i < sz(opGo); i++) {
			cout << opGo[i].X + 1 << ' ' << opGo[i].Y + 1 << endl;
		}
		for (int i = 0; i < sz(opRev); i++) {
			cout << opRev[i].X + 1 << ' ' << opRev[i].Y + 1 << endl;
		}
	}
	return 0;
}


#include <iostream>
#include <vector>
using namespace std;

#define sz(x) ((int)(x).size())

vector <int> row[33];
int jadCol[10000 + 5];
vector <int> selected;
vector <int> y;
vector <int> x;
vector <pair <int, int> > operations;
int n;

// Xor equal the idx1 row by idx2 row
void xorEq(int idx1, int idx2) {
	for (int i = 0; i < n + 1; i++) {
		row[idx1][i] ^= row[idx2][i];
	}
}

// build the index idx of Ys with Xs
// return 0 if can't
int buildThis(int idx) {
	for (int i = 0; i < 33; i++) {
		row[i].clear();
	}
	for (int i = 0; i < n; i++) {
		jadCol[i] = -1;
	}

	// build rows
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < 33; j++) {
			row[j].push_back((x[i] >> j) & 1);
		}
	}
	for (int j = 0; j < 33; j++) {
		row[j].push_back((y[idx] >> j) & 1);
	}

	// gauss elimination
	int par = -1;
	int start = 0;
	for (int i = 0; i < n; i++) {
		int cur = -1;
		for (int j = start; j < 33; j++) {
			if (row[j][i] != 0) {
				cur = j;
				break;
			}
		}

		if (cur != -1) {
			swap(row[start], row[cur]);
			jadCol[i] = par;
			par = i;
			start++;
			for (int j = start; j < 33; j++) {
				if (row[j][i] != 0) {
					xorEq(j, start - 1);
				}
			}
		}
	}

	vector <int> used;
	while (par != -1) {
		used.push_back(par);
		for (int i = start - 2; i >= 0; i--) {
			if (row[i][par] != 0) {
				xorEq(i, start - 1);
			}
		}
		start--;
		par = jadCol[par];
	}

	selected.clear();
	reverse(used.begin(), used.end());
	start = 0;
	int ans = 0;
	bool selfi = false;
	for (int i = 0; i < used.size(); i++) {
		if (row[used[i]][n] == 1) {
			ans ^= x[used[i]];
			selected.push_back(used[i]);
		}
	}

	if (ans == y[idx]) {
		return 1;
	}
	return 0;
}

void swapOperation(int idx1, int idx2) {
	operations.push_back(make_pair(idx1, idx2));
	operations.push_back(make_pair(idx2, idx1));
	operations.push_back(make_pair(idx1, idx2));
	swap(x[idx1], x[idx2]);
}

int main() {
	cin >> n;
	x.resize(n);
	y.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
	}
	char could = 1;
	for (int i = 0; i < n; i++) {
		cin >> y[i];
		int can = buildThis(i);
		if (can == 0) {
			could = 0;
			break;
		}

		bool selfi = false;
		for (int j = 0; j < selected.size(); j++) {
			if (selected[j] == i) {
				selfi = true;
				break;
			}
		}
		int end = sz(selected);
		if (!selfi) {
			int where = selected[sz(selected) - 1];
			if (where > i) {
				swapOperation(i, selected[sz(selected) - 1]);
				end--;
			}
			else {
				operations.push_back(make_pair(i, i));
				x[i] = 0;
			}
		}
		for (int j = 0; j < end; j++) {
			if (selected[j] != i) {
				operations.push_back(make_pair(i, selected[j]));
				x[i] ^= x[selected[j]];
			}
		}
	}

	if (could == 0) {
		cout << -1 << endl;
		return 0;
	}

	cout << operations.size() << endl;
	for (int i = 0; i < operations.size(); i++) {
		cout << operations[i].first + 1 << ' ' << operations[i].second + 1 << endl;
	}

	return 0;
}


/*
Call it liberation or frustration
As it hits like a bomb
Tearing you apart as you're first in line
Entering the zone

Watch how it runs
A nerve wrecking resistance
Watch how it burns
A venomous script's getting formed

You've traveled a long way to get here
And now its waking you up
Waking you up

Walk straight for a final solution
Walk straight, don't you be so cold
Walk straight with a clear resolution
I'll state my case and never turn

Watch how it runs, watch how it burns
And it's all a deception
Break it and learn, there's no return
For a presence like mine

You've traveled a long way to get here
It's getting all so clear now all the things at least
An elapse of conscious progress will last forevermore

My courageous insanity follows an infinite time
I'll be attaching the world on my shoulders
Without a look inside
Inside

Walk straight for a final solution
Walk straight, don't you be so cold
Walk straight with a clear resolution
I'll state my case and never turn

Walk straight for a final solution
Walk straight, don't you be so cold
Walk straight with a clear resolution
*/

//#pragma comment(linker, "/STACK:16777216")
#include <fstream>
#include <iostream>
#include <string>
#include <complex>
#include <math.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <stack>
#include <algorithm>
#include <list>
#include <ctime>
#include <memory.h>

#define y0 sdkfaslhagaklsldk
#define y1 aasdfasdfasdf
#define yn askfhwqriuperikldjk
#define j1 assdgsdgasghsf
#define tm sdfjahlfasfh
#define lr asgasgash

#define eps 1e-11
//#define M_PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define right adsgasgadsg

using namespace std;

vector<pair<long, long> > ops;
vector<pair<long, long> > restore;
long n,q;
vector<long> v1,v2;

void swap(long a,long b,vector<long>& v)
{
 if (a==b)return;
 ops.push_back(make_pair(a,b));
 ops.push_back(make_pair(b,a));
 ops.push_back(make_pair(a,b));
 swap(v[a],v[b]);
}

void xorr(long a,long b,vector<long>& v)
{
 ops.push_back(make_pair(a,b));
 v[a]^=v[b];
}

void run_gauss(vector<long>&v)
{
 long rows=0;
 for (int bit=30;bit>=0;--bit)
 {
     for (int j=rows;j<v.size();j++)
      if (v[j]&(1<<bit))
      {
       swap(j,rows,v);
       for (int k=0;k<v.size();k++)
        if (k!=rows)
         if (v[k]&(1<<bit))
          xorr(k,rows,v);
       ++rows;
       break;
      }
 }
}

int main(){
//freopen("army.in","r",stdin);
//freopen("army.out","w",stdout);
//freopen("C:/input.txt","r",stdin);
//freopen("C:/output.txt","w",stdout);
ios_base::sync_with_stdio(0);
//cin.tie(0);

cin>>n;
for (int i=0;i<n;i++)
{
 cin>>q;
 v1.push_back(q);
}
for (int i=0;i<n;i++)
{
 cin>>q;
 v2.push_back(q);
}

run_gauss(v2);
restore=ops;
ops.clear();
run_gauss(v1);

long er=0;
/*
for (int i=0;i<v1.size();i++)
cout<<v1[i]<<endl;
for (int i=0;i<v2.size();i++)
cout<<v2[i]<<endl;
*/

for (int i=0;i<40&&i<v1.size();i++)
{
 long old=30;
 if (v1[i]==0)continue;
 while ((v1[i]&(1<<old))==0)--old;

 for (int j=0;j<40&&j<v1.size()&&j<v2.size();j++)
  if ((v1[j]^v2[j])&(1<<old))
   xorr(j,i,v1);

}
/*
for (int i=0;i<v1.size();i++)
cout<<v1[i]<<endl;
for (int i=0;i<v2.size();i++)
cout<<v2[i]<<endl;
*/
for (int i=0;i<v1.size();i++)
 if (v1[i]!=v2[i])er=1;

reverse(restore.begin(),restore.end());
for (int i=0;i<restore.size();i++)
 ops.push_back(restore[i]);

if (er)cout<<-1<<endl;
else{
cout<<ops.size()<<endl;
for (int i=0;i<ops.size();i++)
cout<<ops[i].first+1<<" "<<ops[i].second+1<<"\n";
}

cin.get();cin.get();
return 0;}


#include <cstdio>
#include <vector>
using namespace std;

#define n	1000005
#define MK	make_pair
#define PA	pair<int,int>

int		N,A[n],B[n];
vector<PA>	Qa,Qb;

void	Add(int *A,int i,int j,vector<PA> &Q){
		A[i]^=A[j];	Q.push_back(MK(i,j));
}
void	Work(int *A,vector<PA> &Q){
		for	(int i=30,j=1,k;i+1;i--){
			for	(k=j;k<=N&&!(A[k]&(1<<i));k++);
			if	(k>N)	continue;
			if	(k^j)	Add(A,k,j,Q),Add(A,j,k,Q),Add(A,k,j,Q);
			for	(k=1;k<=N;k++)
				if	((A[k]&(1<<i))&&(k!=j))	Add(A,k,j,Q);	j++;
		}
}

int		main(){
		scanf("%d",&N);
		for	(int i=1;i<=N;i++)	scanf("%d",&A[i]);
		for	(int i=1;i<=N;i++)	scanf("%d",&B[i]);
		Work(A,Qa);	Work(B,Qb); int flag=0;
		for	(int i=1,k;i<=N&&A[i];i++){
			for	(k=30;k+1&&!((1<<k)&A[i]);k--);
			for	(int j=1;j<=30&&j<=N;j++)
				if	((A[j]^B[j])&(1<<k))	Add(A,j,i,Qa);
		}

		for	(int i=1;i<=N;i++)
			if	(A[i]!=B[i])	flag=1;
		if	(flag)	puts("-1");
		else{
			printf("%d\n",Qa.size()+Qb.size());
			for	(int i=0,s=Qa.size();i<s;i++)
				printf("%d %d\n",Qa[i].first,Qa[i].second);
			for	(int i=Qb.size()-1;i+1;i--)
				printf("%d %d\n",Qb[i].first,Qb[i].second);
		}
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <deque>
#include <bitset>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <sstream>
using namespace std;

#define DB(x) cerr<<#x<<"="<<x<<" "
#define DBN(x) cerr<<#x<<"="<<x<<"\n"
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define repd(i,r,l) for (int i=(r); i>=(l); i--)
#define rept(i,c) for (typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define sqr(x) ((x)*(x))
#define sz(x) ((int)(x).size())
#define clr(a,v) memset(a,v,sizeof(a))
#define pb push_back
#define mp make_pair

#define lson x+x,l,y
#define rson x+x+1,y+1,r

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<long long, long long> PLL;

#define INF 1000000000
#define EPS (double)1e-9
#define MOD 1000000007
#define PI 3.14159265358979328462
const int maxn = 10000 + 10;
int n;
int x[maxn], y[maxn];
vector<pair<int, int> > ans, ans2, ansMiddle;
int main(int argc, char *argv[])
{
    cin >> n;
    rep(i,1,n)
        scanf("%d", x+i);
    int p = 1;
    repd(i,29,0) {
        rep(j,p,n)
            if (x[j] & (1<<i)) {
                if (j == p) break;
                swap(x[p], x[j]);
                ans.pb(mp(j,p));
                ans.pb(mp(p,j));
                ans.pb(mp(j,p));
                break;
            }
        //
        if (x[p] & (1<<i)) {
            rep(j,1,n)
                if (p != j && (x[j] & (1<<i))) {
                    x[j] ^= x[p];
                    ans.pb(mp(j,p));
                }
            p++;
            if (p == n+1) break;
        }
    }

    // [1, p-1]
    int sumBase = p-1;

    rep(k,1,n)
        scanf("%d", y+k);
    p = 1;
    repd(i,29,0) {
        rep(j,p,n)
            if (y[j] & (1<<i)) {
                if (j == p) break;
                swap(y[p], y[j]);
                ans2.pb(mp(j,p));
                ans2.pb(mp(p,j));
                ans2.pb(mp(j,p));
                break;
            }
        //
        if (y[p] & (1<<i)) {
            rep(j,1,n)
                if (p != j && (y[j] & (1<<i))) {
                    y[j] ^= y[p];
                    ans2.pb(mp(j,p));
                }
            p++;
            if (p == n+1) break;
        }
    }
    reverse(ans2.begin(), ans2.end());

    // [1,sumBase], sumBase<=30
    int wei[33];
    rep(i,1,sumBase) {
        int j = 29; while (!((1<<j) & x[i])) j--;
        wei[i] = j;
        // DB(i);DB(x[i]);DBN(wei[i]);
    }

    // rep(i,1,n) cout << y[i] << endl;
    // transform from base to base
    rep(i,1,n) {
        // y[i]
        if (y[i] == 0) {ansMiddle.pb(mp(i,i)); continue;}
        vector<int> a;
        // cerr << "\n";DBN(i);
        while (y[i] != 0) {
            int j = 29; while (!((1<<j) & y[i])) j--; // 1<<j
            // DB(j);
            bool find = false;
            rep(k,1,sumBase)
                if (wei[k] == j) {
                    find = true;
                    y[i] ^= x[k];
                    a.push_back(k);
                    break;
                }
            if (!find) { printf("-1\n"); exit(0);}
        }
        if (a[0] != i) {ansMiddle.pb(mp(i,i));ansMiddle.pb(mp(i,a[0]));}
        // rept(it, a) { DB(*it);}
        // cerr << "\n";
        for (int k = 1; k < sz(a); k++) ansMiddle.pb(mp(i, a[k]));
    }

    cout << sz(ans)+sz(ans2)+sz(ansMiddle) << "\n";
    rept(it,ans)  printf("%d %d\n", it->first, it->second);
    // printf("...\n");
    rept(it, ansMiddle) printf("%d %d\n", it->first, it->second);
    // printf("!!!\n");
    rept(it,ans2) printf("%d %d\n", it->first, it->second);

    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <deque>
#include <bitset>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <sstream>
using namespace std;

#define DB(x) cerr<<#x<<"="<<x<<" "
#define DBN(x) cerr<<#x<<"="<<x<<"\n"
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define repd(i,r,l) for (int i=(r); i>=(l); i--)
#define rept(i,c) for (typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define sqr(x) ((x)*(x))
#define sz(x) ((int)(x).size())
#define clr(a,v) memset(a,v,sizeof(a))
#define pb push_back
#define mp make_pair

#define lson x+x,l,y
#define rson x+x+1,y+1,r

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<long long, long long> PLL;

#define INF 1000000000
#define EPS (double)1e-9
#define MOD 1000000007
#define PI 3.14159265358979328462
const int maxn = 10000 + 10;
int n;
int x[maxn], y[maxn];
vector<pair<int, int> > ans, ans2, ansMiddle;
int main(int argc, char *argv[])
{
    cin >> n;
    rep(i,1,n)
        scanf("%d", x+i);
    int p = 1;
    repd(i,29,0) {
        rep(j,p,n)
            if (x[j] & (1<<i)) {
                if (j == p) break;
                swap(x[p], x[j]);
                ans.pb(mp(j,p));
                ans.pb(mp(p,j));
                ans.pb(mp(j,p));
                break;
            }
        //
        if (x[p] & (1<<i)) {
            rep(j,1,n)
                if (p != j && (x[j] & (1<<i))) {
                    x[j] ^= x[p];
                    ans.pb(mp(j,p));
                }
            p++;
            if (p == n+1) break;
        }
    }

    // [1, p-1]
    int sumBase = p-1;

    rep(k,1,n)
        scanf("%d", y+k);
    p = 1;
    repd(i,29,0) {
        rep(j,p,n)
            if (y[j] & (1<<i)) {
                if (j == p) break;
                swap(y[p], y[j]);
                ans2.pb(mp(j,p));
                ans2.pb(mp(p,j));
                ans2.pb(mp(j,p));
                break;
            }
        //
        if (y[p] & (1<<i)) {
            rep(j,1,n)
                if (p != j && (y[j] & (1<<i))) {
                    y[j] ^= y[p];
                    ans2.pb(mp(j,p));
                }
            p++;
            if (p == n+1) break;
        }
    }
    reverse(ans2.begin(), ans2.end());

    // [1,sumBase], sumBase<=30
    int wei[33];
    rep(i,1,sumBase) {
        int j = 29; while (!((1<<j) & x[i])) j--;
        wei[i] = j;
    }

    // rep(i,1,n) cout << y[i] << endl;
    // transform from base to base
    rep(i,1,n) {
        // y[i]
        if (y[i] == 0) {ansMiddle.pb(mp(i,i)); continue;}
        vector<int> a;
        while (y[i] != 0) {
            int j = 29; while (!((1<<j) & y[i])) j--; // 1<<j
            bool find = false;
            rep(k,1,sumBase)
                if (wei[k] == j) {
                    find = true;
                    y[i] ^= x[k];
                    a.push_back(k);
                    break;
                }
            if (!find) { printf("-1\n"); exit(0);}
        }
        if (a[0] != i) {ansMiddle.pb(mp(i,i));ansMiddle.pb(mp(i,a[0]));}
        for (int i = 1; i < sz(a); i++) ansMiddle.pb(mp(i, a[i]));
    }

    cout << sz(ans)+sz(ans2)+sz(ansMiddle) << "\n";
    rept(it,ans)  printf("%d %d\n", it->first, it->second);
    rept(it, ansMiddle) printf("%d %d\n", it->first, it->second);
    rept(it,ans2) printf("%d %d\n", it->first, it->second);

    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <deque>
#include <bitset>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <sstream>
using namespace std;

#define DB(x) cerr<<#x<<"="<<x<<" "
#define DBN(x) cerr<<#x<<"="<<x<<"\n"
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define repd(i,r,l) for (int i=(r); i>=(l); i--)
#define rept(i,c) for (typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define sqr(x) ((x)*(x))
#define sz(x) ((int)(x).size())
#define clr(a,v) memset(a,v,sizeof(a))
#define pb push_back
#define mp make_pair

#define lson x+x,l,y
#define rson x+x+1,y+1,r

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<long long, long long> PLL;

#define INF 1000000000
#define EPS (double)1e-9
#define MOD 1000000007
#define PI 3.14159265358979328462
const int maxn = 10000 + 10;
int n;
int x[maxn], y[maxn];
vector<pair<int, int> > ans, ans2;
int main(int argc, char *argv[])
{
    cin >> n;
    rep(i,1,n)
        scanf("%d", x+i);
    int p = 1;
    repd(i,29,0) {
        rep(j,p,n)
            if (x[j] & (1<<i)) {
                if (j == p) break;
                swap(x[p], x[j]);
                ans.pb(mp(j,p));
                ans.pb(mp(p,j));
                ans.pb(mp(j,p));
                break;
            }
        //
        if (x[p] & (1<<i)) {
            rep(j,1,n)
                if (p != j && (x[j] & (1<<i))) {
                    x[j] ^= x[p];
                    ans.pb(mp(j,p));
                }
            p++;
            if (p == n+1) break;
        }
    }

    // [1, p-1]
    int sumBase = p-1;

    rep(k,1,n)
        scanf("%d", y+k);
    p = 1;
    repd(i,29,0) {
        rep(j,p,n)
            if (y[j] & (1<<i)) {
                if (j == p) break;
                swap(y[p], y[j]);
                ans2.pb(mp(j,p));
                ans2.pb(mp(p,j));
                ans2.pb(mp(j,p));
                break;
            }
        //
        if (y[p] & (1<<i)) {
            rep(j,1,n)
                if (p != j && (y[j] & (1<<i))) {
                    y[j] ^= y[p];
                    ans2.pb(mp(j,p));
                }
            p++;
            if (p == n+1) break;
        }
    }
    reverse(ans2.begin(), ans2.end());

    // [1,sumBase], sumBase<=30
    int wei[33];
    rep(i,1,sumBase) {
        int j = 29; while (!((1<<j) & x[i])) j--;
        wei[i] = j;
    }

    // transform from base to base
    rep(i,1,n) {
        // y[i]
        if (y[i] == 0) {ans.pb(mp(i,i)); continue;}
        vector<int> a;
        while (y[i] != 0) {
            int j = 29; while (!((1<<j) & y[i])) j--; // 1<<j
            bool find = false;
            rep(k,1,sumBase)
                if (wei[k] == j) {
                    find = true;
                    y[i] ^= x[k];
                    a.push_back(k);
                    break;
                }
            if (!find) { printf("-1\n"); exit(0);}
        }
        if (a[0] != i) ans.pb(mp(i,i));
        for (int i = 1; i < sz(a); i++) ans.pb(mp(i, a[i]));
    }

    cout << sz(ans)+sz(ans2) << "\n";
    rept(it,ans)  printf("%d %d\n", it->first, it->second);
    rept(it,ans2) printf("%d %d\n", it->first, it->second);

    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <deque>
#include <bitset>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <sstream>
using namespace std;

#define DB(x) cerr<<#x<<"="<<x<<" "
#define DBN(x) cerr<<#x<<"="<<x<<"\n"
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define repd(i,r,l) for (int i=(r); i>=(l); i--)
#define rept(i,c) for (typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define sqr(x) ((x)*(x))
#define sz(x) ((int)(x).size())
#define clr(a,v) memset(a,v,sizeof(a))
#define pb push_back
#define mp make_pair

#define lson x+x,l,y
#define rson x+x+1,y+1,r

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<long long, long long> PLL;

#define INF 1000000000
#define EPS (double)1e-9
#define MOD 1000000007
#define PI 3.14159265358979328462
const int maxn = 10000 + 10;
int n;
int x[maxn], y[maxn];
vector<pair<int, int> > ans, ans2;
int main(int argc, char *argv[])
{
    cin >> n;
    rep(i,1,n)
        scanf("%d", x+i);
    int p = 1;
    repd(i,29,0) {
        rep(j,p,n)
            if (x[j] & (1<<i)) {
                if (j == p) break;
                swap(x[p], x[j]);
                ans.pb(mp(j,p));
                ans.pb(mp(p,j));
                ans.pb(mp(j,p));
                break;
            }
        //
        if (x[p] & (1<<i)) {
            rep(j,1,n)
                if (p != j && (x[j] & (1<<i))) {
                    x[j] ^= x[p];
                    ans.pb(mp(j,p));
                }
            p++;
            if (p == n+1) break;
        }
    }

    // [1, p-1]
    int sumBase = p-1;

    rep(k,1,n)
        scanf("%d", y+k);
    p = 1;
    repd(i,29,0) {
        rep(j,p,n)
            if (y[j] & (1<<i)) {
                if (j == p) break;
                swap(y[p], y[j]);
                ans2.pb(mp(j,p));
                ans2.pb(mp(p,j));
                ans2.pb(mp(j,p));
                break;
            }
        //
        if (y[p] & (1<<i)) {
            rep(j,1,n)
                if (p != j && (y[j] & (1<<i))) {
                    y[j] ^= y[p];
                    ans2.pb(mp(j,p));
                }
            p++;
            if (p == n+1) break;
        }
    }
    reverse(ans2.begin(), ans2.end());

    // [1,sumBase], sumBase<=30
    int wei[33];
    rep(i,1,sumBase) {
        int j = 29; while (!((1<<j) & x[i])) j--;
        wei[i] = j;
    }

    // transform from base to base
    rep(i,1,n) {
        // y[i]
        if (y[i] == 0) {ans.pb(mp(i,i)); continue;}
        vector<int> a;
        while (y[i] != 0) {
            int j = 29; while (!((1<<j) & y[i])) j--; // 1<<j
            bool find = false;
            rep(k,1,sumBase)
                if (wei[k] == j) {
                    find = true;
                    y[i] ^= x[k];
                    a.push_back(k);
                    break;
                }
            if (!find) { printf("-1\n"); exit(0);}
        }
        if (a[0] != i) ans.pb(mp(i,i));
        rept(it,a) ans.pb(mp(i,*it));
    }

    cout << sz(ans)+sz(ans2) << "\n";
    rept(it,ans)  printf("%d %d\n", it->first, it->second);
    rept(it,ans2) printf("%d %d\n", it->first, it->second);

    return 0;
}


#include <cassert>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int n;

const int N = 10005;

int getBit(int x) {
    int ret = 0;
    while (x) {
        x >>= 1;
        ++ret;
    }
    return ret - 1;
}

vector<int> clear(vector<int> &x, vector<pair<int, int> > &ans) {
    int base = 0;
    vector<int> bit;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < base; ++j) {
            if (x[i] >> bit[j] & 1) {
                x[i] ^= x[j];
                ans.push_back(make_pair(i, j));
            }
        }
        if (x[i]) {
            if (i != base) {
                ans.push_back(make_pair(base, i));
                ans.push_back(make_pair(i, base));
                ans.push_back(make_pair(base, i));
                swap(x[i], x[base]);
            }
            bit.push_back(getBit(x[base]));
            ++base;
            for (int j = 0; j < base; ++j) {
                for (int k = j + 1; k < base; ++k) {
                    if (bit[k] > bit[j]) {
                        ans.push_back(make_pair(j, k));
                        ans.push_back(make_pair(k, j));
                        ans.push_back(make_pair(j, k));
                        swap(x[j], x[k]);
                        swap(bit[j], bit[k]);
                    }
                }
            }
            for (int j = 0; j < base; ++j) {
                for (int k = j + 1; k < base; ++k) {
                    if (x[j] >> bit[k] & 1) {
                        ans.push_back(make_pair(j, k));
                        x[j] ^= x[k];
                    }
                }
            }
        }
    }
    return bit;
}

vector<int> x(n), y(n);

bool trans(vector<int> &bitx, vector<int> &bity, vector<pair<int, int> > &mid) {
    int n = bitx.size(), m = bity.size();
    if (n < m) {
        return false;
    }
    int j = 0;
    for (int i = 0; i < n; ++i) {
        if (j == m) {
            mid.push_back(make_pair(i, i));
            x[i] = 0;
            continue;
        }
        if (bitx[i] > bity[j]) {
            mid.push_back(make_pair(i, i));
            x[i] = 0;
            continue;
        }
        if (bitx[i] < bity[j]) {
            return false;
        }
        int delta = x[i] ^ y[j];
        for (int k = i + 1; k < n; ++k) {
            if (delta >> bitx[k] & 1) {
                delta ^= x[k];
                mid.push_back(make_pair(i, k));
            }
        }
        if (delta) {
            return false;
        }
        ++j;
    }
    if (j != m) {
        return false;
    }
    for (int i = n - 1; i >= 0; --i) {
        if (x[i] == 0) {
            for (int j = i; j + 1 < n; ++j) {
                x[j] = x[j + 1];
                mid.push_back(make_pair(j, j + 1));
                mid.push_back(make_pair(j + 1, j + 1));
            }
            x[n - 1] = 0;
            --n;
        }
    }
    return true;
}

bool check(vector<int> x, vector<int> y, vector<pair<int, int> > ans) {
    for (int i = 0; i < (int)ans.size(); ++i) {
        int u = ans[i].first, v = ans[i].second;
        x[u] ^= x[v];
    }
    return x == y;
}

int main() {
    scanf("%d", &n);
    x.resize(n), y.resize(n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &x[i]);
    }
    for (int i = 0; i < n; ++i) {
        scanf("%d", &y[i]);
    }
    vector<int> cx = x, cy = y;
    vector<pair<int, int> > ans1, ans2, mid;
    vector<int> bitx, bity;
    bitx = clear(x, ans1);
    bity = clear(y, ans2);
    if (trans(bitx, bity, mid)) {
        assert(x == y);
        vector<pair<int, int> > full = ans1;
        full.insert(full.end(), mid.begin(), mid.end());
        reverse(ans2.begin(), ans2.end());
        full.insert(full.end(), ans2.begin(), ans2.end());
        printf("%d\n", (int)full.size());
        for (int i = 0; i < (int)full.size(); ++i) {
            printf("%d %d\n", full[i].first + 1, full[i].second + 1);
        }
        assert(check(cx, cy, full));
    } else {
        printf("-1\n");
    }
    return 0;
}


#include <cassert>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int n;

const int N = 10005;

int getBit(int x) {
    int ret = 0;
    while (x) {
        x >>= 1;
        ++ret;
    }
    return ret - 1;
}

vector<int> clear(vector<int> &x, vector<pair<int, int> > &ans) {
    int base = 0;
    vector<int> bit;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < base; ++j) {
            if (x[i] >> bit[j] & 1) {
                x[i] ^= x[j];
                ans.push_back(make_pair(i, j));
            }
        }
        if (x[i]) {
            if (i != base) {
                ans.push_back(make_pair(base, i));
                ans.push_back(make_pair(i, base));
                ans.push_back(make_pair(base, i));
                swap(x[i], x[base]);
            }
            bit.push_back(getBit(x[base]));
            ++base;
            for (int j = 0; j < base; ++j) {
                for (int k = j + 1; k < base; ++k) {
                    if (bit[k] > bit[j]) {
                        ans.push_back(make_pair(j, k));
                        ans.push_back(make_pair(k, j));
                        ans.push_back(make_pair(j, k));
                        swap(x[j], x[k]);
                        swap(bit[j], bit[k]);
                    }
                }
            }
            for (int j = 0; j < base; ++j) {
                for (int k = j + 1; k < base; ++k) {
                    if (x[j] >> bit[k] & 1) {
                        ans.push_back(make_pair(j, k));
                        x[j] ^= x[k];
                    }
                }
            }
        }
    }
    return bit;
}

vector<int> x, y;

bool trans(vector<int> &bitx, vector<int> &bity, vector<pair<int, int> > &mid) {
    int n = bitx.size(), m = bity.size();
    if (n < m) {
        return false;
    }
    int j = 0;
    for (int i = 0; i < n; ++i) {
        if (j == m) {
            mid.push_back(make_pair(i, i));
            x[i] = 0;
            continue;
        }
        if (bitx[i] > bity[j]) {
            mid.push_back(make_pair(i, i));
            x[i] = 0;
            continue;
        }
        if (bitx[i] < bity[j]) {
            return false;
        }
        int delta = x[i] ^ y[j];
        for (int k = i + 1; k < n; ++k) {
            if (delta >> bitx[k] & 1) {
                delta ^= x[k];
                mid.push_back(make_pair(i, k));
                x[i] ^= x[k];
            }
        }
        if (delta) {
            return false;
        }
        ++j;
    }
    if (j != m) {
        return false;
    }
    for (int i = n - 1; i >= 0; --i) {
        if (x[i] == 0) {
            for (int j = i; j + 1 < n; ++j) {
                x[j] = x[j + 1];
                mid.push_back(make_pair(j, j + 1));
                mid.push_back(make_pair(j + 1, j + 1));
            }
            x[n - 1] = 0;
            --n;
        }
    }
    /*
for (int i = 0; i < ::n; ++i) {
    cout << x[i] << ' ';
}
cout << endl;
for (int i = 0; i < ::n; ++i) {
    cout << y[i] << ' ';
}
cout << endl;
    */
    return true;
}

bool check(vector<int> x, vector<int> y, vector<pair<int, int> > ans) {
    for (int i = 0; i < (int)ans.size(); ++i) {
        int u = ans[i].first, v = ans[i].second;
        x[u] ^= x[v];
    }
    return x == y;
}

int main() {
    scanf("%d", &n);
    x.resize(n), y.resize(n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &x[i]);
    }
    for (int i = 0; i < n; ++i) {
        scanf("%d", &y[i]);
    }
    vector<int> cx = x, cy = y;
    vector<pair<int, int> > ans1, ans2, mid;
    vector<int> bitx, bity;
    bitx = clear(x, ans1);
    bity = clear(y, ans2);
    if (trans(bitx, bity, mid)) {
        assert(x == y);
        vector<pair<int, int> > full = ans1;
        full.insert(full.end(), mid.begin(), mid.end());
        reverse(ans2.begin(), ans2.end());
        full.insert(full.end(), ans2.begin(), ans2.end());
        printf("%d\n", (int)full.size());
        for (int i = 0; i < (int)full.size(); ++i) {
            printf("%d %d\n", full[i].first + 1, full[i].second + 1);
        }
        assert(check(cx, cy, full));
    } else {
        printf("-1\n");
    }
    return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#include<iostream>
#include<ctype.h>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<bitset>
#include<iomanip>
#include<complex>
#include<utility>

#define X first
#define Y second
#define REP_0(i,n) for(int i=0;i<(n);++i)
#define REP_1(i,n) for(int i=1;i<=(n);++i)
#define REP_2(i,a,b) for(int i=(a);i<(b);++i)
#define REP_3(i,a,b) for(int i=(a);i<=(b);++i)
#define REP_4(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define DOW_0(i,n) for(int i=(n)-1;-1<i;--i)
#define DOW_1(i,n) for(int i=(n);0<i;--i)
#define DOW_2(i,a,b) for(int i=(b);(a)<i;--i)
#define DOW_3(i,a,b) for(int i=(b);(a)<=i;--i)
#define FOREACH(a,b) for(typeof((b).begin()) a=(b).begin();a!=(b).end();++a)
#define RFOREACH(a,b) for(typeof((b).rbegin()) a=(b).rbegin();a!=(b).rend();++a)
#define PB push_back
#define PF push_front
#define MP make_pair
#define IS insert
#define ES erase
#define IT iterator
#define RI reserve_iterator
#define PQ priority_queue
#define LB lower_bound
#define UB upper_bound
#define ALL(x) x.begin(),x.end()

#define PI 3.1415926535897932384626433832795
#define EXP 2.7182818284590452353602874713527

using namespace std;

typedef long long LL;
typedef long double LD;
typedef double DB;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef pair<int,PII> PIII;
typedef pair<LD,int> PLDI;
typedef vector<PII> VII;

template<class T>
T Mul(T x,T y,T P){
	T F1=0;
	while(y)
	{
		if(y&1)
		{
			F1+=x;
			if(F1<0||F1>=P)F1-=P;
		}
		x<<=1;
		if(x<0||x>=P)x-=P;
		y>>=1;
	}
	return F1;
}

template<class T>
T Pow(T x,T y,T P){
	T F1=1;x%=P;
	while(y)
	{
		if(y&1)
		{
			F1=Mul(F1,x,P);
		}
		x=Mul(x,x,P);
		y>>=1;
	}
	return F1;
}

template<class T>
T Gcd(T x,T y){
	if(y==0)return x;
	T z;
	while(z=x%y){
		x=y,y=z;
	}
	return y;
}

template<class T>
void UpdateMin(T &x,T y){
	if(y<x)
	{
		x=y;
	}
}

template<class T>
void UpdateMax(T &x,T y){
	if(x<y)
	{
		x=y;
	}
}

template<class T>
T Sqr(const T x){
	return x*x;
}

template<class T>
T Abs(const T x){
	return x<0?-x:x;
}

#define MaxBuffer 20000000
class ReadBuffer{
	private:
	char buff[MaxBuffer];
	char *buf;
	public:
	void init(int size=MaxBuffer)
	{
		fread(buff,1,size,stdin);
		buf=buff;
	}
	template<class T>
	bool readInteger(T &x)
	{
		x=0;
		while(*buf&&isspace(*buf)) ++buf;
		if(*buf==0) return false;
		static bool flag;
		flag=0;
		if(*buf=='-') flag=true;
		else x=*buf-'0';
		while(isdigit(*++buf)) x=x*10+*buf-'0';
		if(flag) x=-x;
		return true;
	}
	template<class T>
	bool readFloat(T &x)
	{
		long double nowpos=0.1;
		x=0;
		while(*buf&&isspace(*buf)) ++buf;
		if(*buf==0) return false;
		static bool flag,decimal;
		decimal=flag=0;
		if(*buf=='-') flag=true,++buf;
		else if(*buf=='.') decimal=true;
		while(isdigit(*buf)||*buf=='.')
		{
			if(*buf=='.') decimal=true;
			else
			{
				if(decimal)
				{
					x+=nowpos*(*buf-'0');
					nowpos*=0.1;
				}
				else
				{
					x=x*10+*buf-'0';
				}
			}
			++buf;
		}
		return true;
	}
	bool readChar(char c)
	{
		if(*buf==0) return 0;
		return c=*buf++,1;
	}
	bool readString(char *s)
	{
		while(*buf&&isspace(*buf)) ++buf;
		if(!*buf) return false;
		while(!isspace(*buf)) *s++=*buf++;
		*s++=0;
		return true;
	}
	int countSpacetonext(){
		int total=0;
		while(*buf&&*buf==' ') ++total,++buf;
		return total;
	}
	bool splitBycharactor(char *s,char Split='\n'){
		while(*buf&&*buf!=Split) *s++=*buf++;
		*s++=0;
		return *buf!=0;
	}
};

struct EDGE{
	int T;EDGE *Nxt;
};

vector<PII> V;
stack<PII> S;
int N;
int a[21001],b[21001];
int sta[21001],stb[21001];
int main(){
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	scanf("%d",&N);
	REP_1(i,N) scanf("%d",a+i);
	REP_1(i,N) scanf("%d",b+i);
	REP_1(i,N){
		int k=i;
		REP_3(j,i,N) if(a[j]>a[k]) k=j;
		if(a[k]==0) break;
		if(k!=i){
			V.push_back(MP(k,i));
			V.push_back(MP(i,k));
			V.push_back(MP(k,i));
			swap(a[k],a[i]);
		}
		for(int j=1<<30;j;j>>=1) if(j&a[i]){
			sta[i]=j;
			break;
		}
		REP_1(j,N) if(j!=i&&(sta[i]&a[j])){
			V.push_back(MP(j,i));
			a[j]^=a[i];
		}
	}
	REP_1(i,N){
		int k=i;
		REP_3(j,i,N) if(b[j]>b[k]) k=j;
		if(b[k]==0) break;
		if(k!=i){
			S.push(MP(k,i));
			S.push(MP(i,k));
			S.push(MP(k,i));
			swap(b[k],b[i]);
		}
		for(int j=1<<30;j;j>>=1) if(j&b[i]){
			stb[i]=j;
			break;
		}
		REP_1(j,N) if(j!=i&&(stb[i]&b[j])){
			S.push(MP(j,i));
			b[j]^=b[i];
		}
	}
	REP_1(i,N) if(a[i]!=b[i]){
		if(sta[i]<stb[i]){
			printf("-1\n");
			return 0;
		}
		else if(sta[i]>stb[i]){
			V.push_back(MP(i,i));
			a[i]=0;
			sta[i]=0;
			REP_3(j,i+1,N) if(a[j]!=0){
				V.push_back(MP(j-1,j));
				V.push_back(MP(j,j-1));
				V.push_back(MP(j-1,j));
				swap(a[j],a[j-1]);
				swap(sta[j],sta[j-1]);
			}
		}
		else{
			REP_3(j,i+1,N){
				if(a[j]==0) break;
				if(sta[j]&b[i]){
					V.push_back(MP(i,j));
					a[i]^=a[j];
				}
			}
			if(a[i]!=b[i]){
				printf("-1\n");
				return 0;
			}
		}
	}
	while(!S.empty()){
		V.push_back(S.top());
		S.pop();
	}
	printf("%d\n",(int)V.size());
	REP_0(i,int(V.size())){
		printf("%d %d\n",V[i].X,V[i].Y);
	}
	scanf("%d",&N);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#include<iostream>
#include<ctype.h>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<bitset>
#include<iomanip>
#include<complex>
#include<utility>

#define X first
#define Y second
#define REP_0(i,n) for(int i=0;i<(n);++i)
#define REP_1(i,n) for(int i=1;i<=(n);++i)
#define REP_2(i,a,b) for(int i=(a);i<(b);++i)
#define REP_3(i,a,b) for(int i=(a);i<=(b);++i)
#define REP_4(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define DOW_0(i,n) for(int i=(n)-1;-1<i;--i)
#define DOW_1(i,n) for(int i=(n);0<i;--i)
#define DOW_2(i,a,b) for(int i=(b);(a)<i;--i)
#define DOW_3(i,a,b) for(int i=(b);(a)<=i;--i)
#define FOREACH(a,b) for(typeof((b).begin()) a=(b).begin();a!=(b).end();++a)
#define RFOREACH(a,b) for(typeof((b).rbegin()) a=(b).rbegin();a!=(b).rend();++a)
#define PB push_back
#define PF push_front
#define MP make_pair
#define IS insert
#define ES erase
#define IT iterator
#define RI reserve_iterator
#define PQ priority_queue
#define LB lower_bound
#define UB upper_bound
#define ALL(x) x.begin(),x.end()

#define PI 3.1415926535897932384626433832795
#define EXP 2.7182818284590452353602874713527

using namespace std;

typedef long long LL;
typedef long double LD;
typedef double DB;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef pair<int,PII> PIII;
typedef pair<LD,int> PLDI;
typedef vector<PII> VII;

template<class T>
T Mul(T x,T y,T P){
	T F1=0;
	while(y)
	{
		if(y&1)
		{
			F1+=x;
			if(F1<0||F1>=P)F1-=P;
		}
		x<<=1;
		if(x<0||x>=P)x-=P;
		y>>=1;
	}
	return F1;
}

template<class T>
T Pow(T x,T y,T P){
	T F1=1;x%=P;
	while(y)
	{
		if(y&1)
		{
			F1=Mul(F1,x,P);
		}
		x=Mul(x,x,P);
		y>>=1;
	}
	return F1;
}

template<class T>
T Gcd(T x,T y){
	if(y==0)return x;
	T z;
	while(z=x%y){
		x=y,y=z;
	}
	return y;
}

template<class T>
void UpdateMin(T &x,T y){
	if(y<x)
	{
		x=y;
	}
}

template<class T>
void UpdateMax(T &x,T y){
	if(x<y)
	{
		x=y;
	}
}

template<class T>
T Sqr(const T x){
	return x*x;
}

template<class T>
T Abs(const T x){
	return x<0?-x:x;
}

#define MaxBuffer 20000000
class ReadBuffer{
	private:
	char buff[MaxBuffer];
	char *buf;
	public:
	void init(int size=MaxBuffer)
	{
		fread(buff,1,size,stdin);
		buf=buff;
	}
	template<class T>
	bool readInteger(T &x)
	{
		x=0;
		while(*buf&&isspace(*buf)) ++buf;
		if(*buf==0) return false;
		static bool flag;
		flag=0;
		if(*buf=='-') flag=true;
		else x=*buf-'0';
		while(isdigit(*++buf)) x=x*10+*buf-'0';
		if(flag) x=-x;
		return true;
	}
	template<class T>
	bool readFloat(T &x)
	{
		long double nowpos=0.1;
		x=0;
		while(*buf&&isspace(*buf)) ++buf;
		if(*buf==0) return false;
		static bool flag,decimal;
		decimal=flag=0;
		if(*buf=='-') flag=true,++buf;
		else if(*buf=='.') decimal=true;
		while(isdigit(*buf)||*buf=='.')
		{
			if(*buf=='.') decimal=true;
			else
			{
				if(decimal)
				{
					x+=nowpos*(*buf-'0');
					nowpos*=0.1;
				}
				else
				{
					x=x*10+*buf-'0';
				}
			}
			++buf;
		}
		return true;
	}
	bool readChar(char c)
	{
		if(*buf==0) return 0;
		return c=*buf++,1;
	}
	bool readString(char *s)
	{
		while(*buf&&isspace(*buf)) ++buf;
		if(!*buf) return false;
		while(!isspace(*buf)) *s++=*buf++;
		*s++=0;
		return true;
	}
	int countSpacetonext(){
		int total=0;
		while(*buf&&*buf==' ') ++total,++buf;
		return total;
	}
	bool splitBycharactor(char *s,char Split='\n'){
		while(*buf&&*buf!=Split) *s++=*buf++;
		*s++=0;
		return *buf!=0;
	}
};

struct EDGE{
	int T;EDGE *Nxt;
};

vector<PII> V;
stack<PII> S;
int N;
int a[21001],b[21001];
int sta[21001],stb[21001];
int main(){
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	scanf("%d",&N);
	REP_1(i,N) scanf("%d",a+i);
	REP_1(i,N) scanf("%d",b+i);
	REP_1(i,N){
		int k=i;
		REP_3(j,i,N) if(a[j]>a[k]) k=j;
		if(a[k]==0) break;
		if(k!=i){
			V.push_back(MP(k,i));
			V.push_back(MP(i,k));
			V.push_back(MP(k,i));
			swap(a[k],a[i]);
		}
		for(int j=1<<30;j;j>>=1) if(j&a[i]){
			sta[i]=j;
			break;
		}
		REP_1(j,N) if(j!=i&&(sta[i]&a[j])){
			V.push_back(MP(j,i));
			a[j]^=a[i];
		}
	}
	REP_1(i,N){
		int k=i;
		REP_3(j,i,N) if(b[j]>b[k]) k=j;
		if(b[k]==0) break;
		if(k!=i){
			S.push(MP(k,i));
			S.push(MP(i,k));
			S.push(MP(k,i));
			swap(b[k],b[i]);
		}
		for(int j=1<<30;j;j>>=1) if(j&b[i]){
			stb[i]=j;
			break;
		}
		REP_1(j,N) if(j!=i&&(stb[i]&b[j])){
			S.push(MP(j,i));
			b[j]^=b[i];
		}
	}
	REP_1(i,N) if(a[i]!=b[i]){
		if(sta[i]<stb[i]){
			printf("-1\n");
			return 0;
		}
		else if(sta[i]>stb[i]){
			V.push_back(MP(i,i));
			a[i]=0;
			sta[i]=0;
			REP_3(j,i+1,N) if(a[j]!=0){
				V.push_back(MP(j-1,j));
				V.push_back(MP(j,j-1));
				V.push_back(MP(j-1,j));
				swap(a[j],a[j-1]);
				swap(sta[j],sta[j-1]);
			}
			--i;
		}
		else{
			REP_3(j,i+1,N){
				if(a[j]==0) break;
				if(sta[j]&b[i]){
					V.push_back(MP(i,j));
					a[i]^=a[j];
				}
			}
			if(a[i]!=b[i]){
				printf("-1\n");
				return 0;
			}
		}
	}
	while(!S.empty()){
		V.push_back(S.top());
		S.pop();
	}
	printf("%d\n",(int)V.size());
	REP_0(i,int(V.size())){
		printf("%d %d\n",V[i].X,V[i].Y);
	}
	scanf("%d",&N);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cassert>
#include <cctype>
using namespace std;
typedef long long LL;
const int N = 10005;
const int M = 200005;
int n , X[N] , Y[N];
int p[N] , q[N];
int a[N] , b[N] , c[30] , d[30];
vector<int> baseA , baseB;
bool f[N] , g[N];
vector< pair<int , int> > resA;
vector< pair<int , int> > resB;
map<int , int> hashA , hashB;

void work() {
    int i , j , k , x , y;
    scanf("%d",&n);
    for (i = 0 ; i < n ; ++ i)
        scanf("%d",&X[i]);
    for (i = 0 ; i < n ; ++ i)
        scanf("%d",&Y[i]);
    memcpy(a , X , sizeof(a));
    memset(p , -1 , sizeof(p));
    memset(c , -1 , sizeof(c));
    for (j = 29 ; j >= 0 ; -- j) {
        x = -1;
        for (i = 0 ; i < n ; ++ i)
            if (!~p[i] && (a[i] >> j & 1)) {
                x = i;
                break;
            }
        if (!~x) continue; p[x] = j , c[j] = x;
        for (i = 0 ; i < n ; ++ i)
            if ((x != i) && (a[i] >> j & 1)) {
                a[i] ^= a[x];
                resA.push_back(make_pair(i , x));
            }
    }
    for (i = 0 ; i < n ; ++ i)
        if (a[i]) {
            baseA.push_back(a[i]);
            hashA[a[i]] = i;
        }
    memcpy(b , Y , sizeof(b));
    memset(q , -1 , sizeof(q));
    memset(d , -1 , sizeof(d));
    for (j = 29 ; j >= 0 ; -- j) {
        x = -1;
        for (i = 0 ; i < n ; ++ i)
            if (!~q[i] && (b[i] >> j & 1)) {
                x = i;
                break;
            }
        if (!~x) continue; q[x] = j , d[j] = x;
        for (i = 0 ; i < n ; ++ i)
            if ((x != i) && (b[i] >> j & 1)) {
                b[i] ^= b[x];
                resB.push_back(make_pair(i , x));
            }
    }
    for (i = 0 ; i < n ; ++ i)
        if (b[i]) {
            baseB.push_back(b[i]);
            hashB[b[i]] = i;
        }
    sort(baseA.begin() , baseA.end() , greater<int>());
    sort(baseB.begin() , baseB.end() , greater<int>());
//    for (i = 0 ; i < baseA.size() ; ++ i)
//        printf("%d%c" , baseA[i] , " \n"[i + 1 == baseA.size()]);
//    for (i = 0 ; i < baseB.size() ; ++ i)
//        printf("%d%c" , baseB[i] , " \n"[i + 1 == baseB.size()]);

    for (j = 0 ; j < baseB.size() ; ++ j) {
        x = baseB[j];
        for (k = 29 ; k >= 0 ; -- k) {
            if (x >> k & 1) {
                for (i = 0 ; i < baseA.size() ; ++ i)
                    if (baseA[i] >> k & 1) {
                        x ^= baseA[i];
                        if (!f[i] && !g[j]) {
                            f[i] = g[j] = 1;
                            int L = hashA[baseA[i]]; // L -> R
                            int R = hashB[baseB[j]];
                            if (L != R) {
                                resA.push_back(make_pair(L , R)) , a[L] ^= a[R];
                                resA.push_back(make_pair(R , L)) , a[R] ^= a[L];
                                resA.push_back(make_pair(L , R)) , a[L] ^= a[R];
                                hashA[a[L]] = L;
                                hashA[a[R]] = R;
                                swap(p[L] , p[R]);
                                c[p[L]] = L;
                                c[p[R]] = R;
                            }
                            //cout << "papa : " << L << ' ' << R << endl;
                        }
                        break;
                    }
            }
        }
        if (x)
            break;
    }
    if (j < baseB.size()) {
        puts("-1");
        return;
    }

//    for (i = 0 ; i < n ; ++ i)
//        printf("%d%c" , a[i] , " \n"[i + 1 == n]);
//    for (i = 0 ; i < n ; ++ i)
//        printf("%d%c" , b[i] , " \n"[i + 1 == n]);
    // a -> b

    for (k = 29 ; k >= 0 ; -- k) {
        if (!~c[k]) continue;

        i = c[k];
        for (i = 0 ; i < n ; ++ i)
            if (i != c[k] && ((a[i] ^ b[i]) >> k & 1)) {
                resA.push_back(make_pair(i , c[k]));
                a[i] ^= a[c[k]];
            }
        i = c[k];
        if ((a[i] ^ b[i]) >> k & 1) {
            resA.push_back(make_pair(i , i));
            a[i] ^= a[i];
        }
    }

//    puts("****************");
//    for (i = 0 ; i < n ; ++ i)
//        printf("%d%c" , a[i] , " \n"[i + 1 == n]);
//    for (i = 0 ; i < n ; ++ i)
//        printf("%d%c" , b[i] , " \n"[i + 1 == n]);
//    puts("****************");
    cout << resA.size() + resB.size() << endl;
    for (i = 0 ; i < resA.size() ; ++ i) {
        printf("%d %d\n" , resA[i].first + 1 , resA[i].second + 1);
        X[resA[i].first] ^= X[resA[i].second];
    }
    reverse(resB.begin() , resB.end());
    for (i = 0 ; i < resB.size() ; ++ i) {
        printf("%d %d\n" , resB[i].first + 1 , resB[i].second + 1);
        X[resB[i].first] ^= X[resB[i].second];
    }
//    puts("****************");
//    for (i = 0 ; i < n ; ++ i)
//        printf("%d%c" , X[i] , " \n"[i + 1 == n]);
//    for (i = 0 ; i < n ; ++ i)
//        printf("%d%c" , Y[i] , " \n"[i + 1 == n]);
}

int main() {
    work();
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
#define pii pair<int,int>
const int MAXN = 10010;
int a[MAXN];
int b[MAXN];
int n;
vector<pii>qa,qb;

void Xor(int *a,int i,int j,vector<pii> &q)
{
    q.push_back(make_pair(i,j));
    a[i]^=a[j];
}

void guass(int *a,vector<pii> &q)
{
    int p=0;
    for(int i=29;i>=0;i--){
        for(int j=p;j<n;j++){
            if(a[j]&(1<<i)){
                if(j!=p){
                    Xor(a,p,j,q);
                    Xor(a,j,p,q);
                    Xor(a,p,j,q);
                }
                for(int k=0;k<n;k++){
                    if(k!=p && a[k]&(1<<i)){
                        Xor(a,k,p,q);
                    }
                }
                ++p;
                break;
            }
        }
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%d",&a[i]);
    for(int i=0;i<n;i++)scanf("%d",&b[i]);
    guass(a,qa);
    guass(b,qb);
    for(int i=0;i<30 && i<n;i++){
        if(a[i]==0)break;
        int k=(1<<29);
        while(!(k&a[i]))k>>=1;
        for(int j=0;j<30&&j<n;j++){
            if((a[j]^b[j])&k){
                Xor(a,j,i,qa);
            }
        }
    }
    int ok=1;
    for(int i=0;i<n;i++)if(a[i]!=b[i]){
        ok=0;
        break;
    }
    if(!ok)printf("-1\n");
    else {
        printf("%d\n",qa.size()+qb.size());
        for(int i=0;i<qa.size();i++)printf("%d %d\n",qa[i].first+1,qa[i].second+1);
        reverse(qb.begin(),qb.end());
        for(int i=0;i<qb.size();i++)printf("%d %d\n",qb[i].first+1,qb[i].second+1);
    }
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
using namespace std;
vector<pair<long, long> >ops;
vector<pair<long, long> >restore;
long n,q;
vector<long>v1,v2;
void swap(long a,long b,vector<long>& v)
{
    if (a==b)return;
    ops.push_back(make_pair(a,b));
    ops.push_back(make_pair(b,a));
    ops.push_back(make_pair(a,b));
    swap(v[a],v[b]);
}
void xorr(long a,long b,vector<long>& v)
{
    ops.push_back(make_pair(a,b));
    v[a]^=v[b];
}
void run_gauss(vector<long>&v)
{
    long rows=0;
    for (int bit=30;bit>=0;--bit)
    {
        for (int j=rows;j<v.size();j++)
        if (v[j]&(1<<bit))
        {
            swap(j,rows,v);
            for (int k=0;k<v.size();k++) if(k!=rows&&(v[k]&(1<<bit))) xorr(k,rows,v);
            ++rows;
            break;
        }
    }
}
int main()
{
    //ios_base::sync_with_stdio(0);
    cin>>n;
    for (int i=0;i<n;i++)
    {
        cin>>q;
        v1.push_back(q);
    }
    for (int i=0;i<n;i++)
    {
        cin>>q;
        v2.push_back(q);
    }
    run_gauss(v2);
    restore=ops;
    ops.clear();
    run_gauss(v1);
    long er=0;
    for (int i=0;i<40&&i<v1.size();i++)
    {
        long old=30;
        if (v1[i]==0)continue;
        while ((v1[i]&(1<<old))==0)--old;
        for (int j=0;j<40&&j<v1.size()&&j<v2.size();j++)
        if ((v1[j]^v2[j])&(1<<old)) xorr(j,i,v1);
    }
    for (int i=0;i<v1.size();i++) if (v1[i]!=v2[i])er=1;
    reverse(restore.begin(),restore.end());
    for (int i=0;i<restore.size();i++)
    ops.push_back(restore[i]);
    if(er) cout<<-1<<endl;
    else
    {
        cout<<ops.size()<<endl;
        for (int i=0;i<ops.size();i++)
        cout<<ops[i].first+1<<" "<<ops[i].second+1<<"\n";
    }
    return 0;
}


#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef __int64 LL;
int n,cnt_a=0,cnt_b=0;
LL a[10005],b[10005],pw[35];
struct operation
{
    int x,y;
    operation(int _x=-1,int _y=-1) {x=_x;y=_y;}
}qa[1000005],qb[1000005];
void Swap(int x,int y,LL *t,operation *q,int &cnt)
{
    if(x==y) return;
    q[cnt++]=operation(x,y);
    q[cnt++]=operation(y,x);
    q[cnt++]=operation(x,y);
    LL tp=t[x];
    t[x]=t[y];
    t[y]=tp;
}
void Do(int x,int y,LL *t,operation *q,int &cnt)
{
    q[cnt++]=operation(x,y);
    t[x]^=t[y];
}
void Gauss(LL *t,operation *q,int &cnt)
{
    cnt=0;
    int r=0;
    for(int i=30;i>=0;i--)
    {
        for(int j=r;j<n;j++)
        {
            if(t[j]&pw[i])
            {
                Swap(j,r,t,q,cnt);
                for(int k=0;k<n;k++)
                {
                    if(k==r) continue;
                    if(t[k]&pw[i]) Do(k,r,t,q,cnt);
                }
                r++;
                break;
            }
        }
    }
}
int main()
{
    pw[0]=1;
    for(int i=1;i<=32;i++) pw[i]=pw[i-1]*2;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%I64d",&a[i]);
    for(int i=0;i<n;i++) scanf("%I64d",&b[i]);
    Gauss(a,qa,cnt_a);
    Gauss(b,qb,cnt_b);
    for(int i=0;i<40&&i<n;i++)
    {
        int p=30;
        if(a[i]==0) continue;
        while((a[i]&pw[p])==0) p--;
        for(int j=0;j<40&&j<n;j++) if((a[j]^b[j])&pw[p]) Do(j,i,a,qa,cnt_a);
    }
    for(int i=0;i<n;i++) if(a[i]!=b[i]) {printf("-1\n");return 0;}
    printf("%d\n",cnt_a+cnt_b);
    for(int i=0;i<cnt_a;i++) printf("%d %d\n",qa[i].x+1,qa[i].y+1);
    for(int i=cnt_b-1;i>=0;i--) printf("%d %d\n",qb[i].x+1,qb[i].y+1);
    return 0;
}


#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<fstream>
#include<math.h>
#include<iomanip>
#include<time.h>
#include<assert.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define inf 1000000007
#define mod 1000000007
#define pii pair<int,int>
#define vi vector<int>
#define vii vector<pii>
#define VS vector<string>
#define all(x) x.begin(),x.end()
#define mp make_pair
#define pb push_back
#define x first
#define y second
#define N 50010
#define pi 3.14159265358979323846
#define DBG(vari) cerr<<#vari<<"="<<(vari)<<endl;
#define FOREACH(i,t) for(__typeof(t.begin()) i=t.begin();i!=t.end();i++)

int gauss(vi &v,vii &ans,vi &mb)
{
    int cur=0;
    for(int b=30;b>=0;b--)if(cur<v.size())
    {
        for(int i=cur;i<v.size();i++)if(v[i]>>b&1){
        if(i!=cur)
        {
            swap(v[i],v[cur]);
            ans.pb(mp(i,cur));
            ans.pb(mp(cur,i));
            ans.pb(mp(i,cur));
        }
        break;
        }
        if(v[cur]>>b&1)
        {
            for(int i=0;i<v.size();i++)
                if(i!=cur&&(v[i]>>b&1))
                v[i]^=v[cur],ans.pb(mp(i,cur));
            mb.pb(1<<b);cur++;
        }
    }
    return cur;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int T,i,j,m,ca=0,k,n;
    vi x,y;
    scanf("%d",&n);
    x.resize(n),y.resize(n);
    for(i=0;i<n;i++)scanf("%d",&x[i]);
    for(i=0;i<n;i++)scanf("%d",&y[i]);
    vii ans;vi mb;
    int b=gauss(x,ans,mb);
    vi y0=y;
    for(i=0;i<y.size();i++)
    {
        for(j=0;j<b;j++)if((y[i]&x[j])>=mb[j])
        {
            y[i]^=x[j];
            if(i>=b)ans.pb(mp(i,j));
        }
        if(y[i]){puts("-1");return 0;}
    }
    y0.resize(b);
    vii ansy;vi mby;
    gauss(y0,ansy,mby);
    y=y0;
    for(i=0;i<y.size();i++)
    {
        if((x[i]&y[i])>=mb[i])y[i]^=x[i];
        else ans.pb(mp(i,i));
        for(j=i+1;j<b;j++)if((y[i]&x[j])>=mb[j])
            y[i]^=x[j],ans.pb(mp(i,j));
    }
    for(i=ansy.size()-1;i>=0;i--)
        ans.pb(mp(ansy[i].x,ansy[i].y));
    printf("%d\n",ans.size());
    for(i=0;i<ans.size();i++)
        printf("%d %d\n",ans[i].x+1,ans[i].y+1);
    return 0;
}


#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<fstream>
#include<math.h>
#include<iomanip>
#include<time.h>
#include<assert.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define inf 1000000007
#define mod 1000000007
#define pii pair<int,int>
#define vi vector<int>
#define vii vector<pii>
#define VS vector<string>
#define all(x) x.begin(),x.end()
#define mp make_pair
#define pb push_back
#define x first
#define y second
#define N 50010
#define pi 3.14159265358979323846
#define DBG(vari) cerr<<#vari<<"="<<(vari)<<endl;
#define FOREACH(i,t) for(__typeof(t.begin()) i=t.begin();i!=t.end();i++)

int gauss(vi &v,vii &ans,vi &mb)
{
    int cur=0;
    for(int b=30;b>=0;b--)if(cur<v.size())
    {
        for(int i=cur;i<v.size();i++)if(v[i]>>b&1){
        if(i!=cur)
        {
            swap(v[i],v[cur]);
            ans.pb(mp(i,cur));
            ans.pb(mp(cur,i));
            ans.pb(mp(i,cur));
        }
        break;
        }
        if(v[cur]>>b&1)
        {
            for(int i=0;i<v.size();i++)
                if(i!=cur&&(v[i]>>b&1))
                v[i]^=v[cur],ans.pb(mp(i,cur));
            mb.pb(1<<b);cur++;
        }
    }
    return cur;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int T,i,j,m,ca=0,k,n;
    vi x,y;
    scanf("%d",&n);
    x.resize(n),y.resize(n);
    for(i=0;i<n;i++)scanf("%d",&x[i]);
    for(i=0;i<n;i++)scanf("%d",&y[i]);
    vii ans;vi mb;
    int b=gauss(x,ans,mb);
    DBG(b)
    vi y0=y;
    for(i=0;i<y.size();i++)
    {
        for(j=0;j<b;j++)if(y[i]&x[j])
        {
            y[i]^=x[j];
            if(i>=b)ans.pb(mp(i,j));
        }
        if(y[i]){puts("-1");return 0;}
    }
    y0.resize(b);
    vii ansy;vi mby;
    gauss(y0,ansy,mby);
    y=y0;
    for(i=0;i<y.size();i++)
    {
        if((x[i]&y[i])>=mb[i])y[i]^=x[i];
        else ans.pb(mp(i,i));
        for(j=i+1;j<b;j++)if((y[i]&x[j])>=mb[j])
            y[i]^=x[j],ans.pb(mp(i,j));
    }
    for(i=ansy.size()-1;i>=0;i--)
        ans.pb(mp(ansy[i].x,ansy[i].y));
    printf("%d\n",ans.size());
    for(i=0;i<ans.size();i++)
        printf("%d %d\n",ans[i].x+1,ans[i].y+1);
    return 0;
}


#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

int n;
int x[100000];
int y[100000];

vector<int> base;

int t[100000][30];
int indice[100000];
int desp[30];
int esbase[100000];

vector<pair<int,int> > sol;

void asigna(int i,int j)
{
  x[i]^=x[j];
  sol.push_back(pair<int,int> (i,j));
}

void obtenbase()
{
  for (int i=0;i<n;i++) {
    for (int j=0;j<30;j++)
      t[i][j]=((y[i]&(1<<j))!=0);
    indice[i]=i;
  }
  for (int i=0;i<n;i++) {
    if (i>0) desp[i]=desp[i-1]+1;
    for (;desp[i]<30;desp[i]++) {
      for (int ii=i;ii<n;ii++) {
	if (t[ii][desp[i]]!=0) {
	  for (int j=desp[i];j<30;j++)
	    swap(t[ii][j],t[i][j]);
	  swap(indice[i],indice[ii]);
	  break;
	}
      }
      if (t[i][desp[i]]!=0) break;
    }
    if (desp[i]==30) {
      sort(base.begin(),base.end());
      return;
    }
    base.push_back(indice[i]);
    esbase[indice[i]]=1;
    for (int ii=i+1;ii<n;ii++) {
      if (t[ii][desp[i]]!=0) {
	for (int j=desp[i];j<30;j++)
	  t[ii][j]^=t[i][j];
      }
    }
  }
  sort(base.begin(),base.end());
}

int m[30][100000];

int nn;

int a[100000];
int jj[30];

void genera()
{
  for (int j=0;j<nn;j++)
    a[j]=0;
  for (int i=0;i<30;i++) {
    if (i==0) jj[i]=0;
    else jj[i]=jj[i-1]+1;
    while (jj[i]<nn and m[i][jj[i]]==0) {
      for (int ii=i;ii<30;ii++) {
	if (m[ii][jj[i]]!=0) {
	  for (int j=jj[i];j<=nn;j++)
	    swap(m[ii][j],m[i][j]);
	  break;
	}
      }
      if (m[i][jj[i]]==0) jj[i]++;
    }
    if (jj[i]<nn) {
      for (int ii=i+1;ii<30;ii++)
	if (m[ii][jj[i]]!=0)
	  for (int j=jj[i];j<=nn;j++)
	    m[ii][j]^=m[i][j];
    } else {
      for (int ii=i+1;ii<30;ii++)
	jj[ii]=nn;
      break;
    }
  }
  for (int i=29;i>=0;i--) {
    if (jj[i]==nn) {
      if (m[i][nn]!=0) {
	cout<<-1<<endl;
	exit(0);
      }
    } else {
      a[jj[i]]=m[i][nn];
      for (int j=nn-1;j>jj[i];j--)
	a[jj[i]]^=(m[i][j]&a[j]);
    }
  }
}

void obtener(int iy)
{
  for (int i=0;i<30;i++) {
    for (int j=0;j<int(base.size());j++)
      m[i][j]=((y[base[j]]&(1<<i))!=0);
    m[i][int(base.size())]=((y[iy]&(1<<i))!=0);
  }
  nn=int(base.size());
  genera();
  asigna(iy,iy);
  for (int i=0;i<int(base.size());i++)
    if (a[i])
      asigna(iy,base[i]);
}

void calcula(int iy)
{
  for (int i=0;i<30;i++) {
    for (int j=0;j<n;j++)
      m[i][j]=((x[j]&(1<<i))!=0);
    m[i][n]=((y[iy]&(1<<i))!=0);
  }
  nn=n;
  genera();
}

int main()
{
  cin>>n;
  for (int i=0;i<n;i++)
    cin>>x[i];
  for (int i=0;i<n;i++)
    cin>>y[i];
  obtenbase();
  /*
  cout<<"base:";
  for (int i=0;i<int(base.size());i++)
    cout<<base[i]<<",";
  cout<<endl;
  */
  for (int k=0;k<int(base.size());k++) {
    int i=base[k];
    calcula(i);
    if (a[i]==0) {
      int ix=-1;
      for (int j=0;j<n;j++) {
	if (a[j] and (j>i or not esbase[j])) {
	  ix=j;
	  break;
	}
      }
      asigna(i,ix);
      asigna(ix,i);
      asigna(i,ix);
      a[ix]=0;
    } else {
      a[i]=0;
    }
    for (int j=0;j<n;j++)
      if (a[j])
	asigna(i,j);
  }
  for (int i=0;i<n;i++)
    if (not esbase[i])
      obtener(i);
  cout<<int(sol.size())<<endl;
  for (int i=0;i<int(sol.size());i++)
    cout<<sol[i].first+1<<" "<<sol[i].second+1<<endl;
}


#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>

using namespace std;

int n;
int x[100000];
int y[100000];

vector<int> base;

int t[100000][30];
int indice[100000];
int desp[30];
int esbase[100000];

vector<pair<int,int> > sol;

void asigna(int i,int j)
{
  x[i]^=x[j];
  sol.push_back(pair<int,int> (i,j));
}

void obtenbase()
{
  for (int i=0;i<n;i++) {
    for (int j=0;j<30;j++)
      t[i][j]=((y[i]&(1<<j))!=0);
    indice[i]=i;
  }
  for (int i=0;i<n;i++) {
    if (i>0) desp[i]=desp[i-1]+1;
    for (;desp[i]<30;desp[i]++) {
      for (int ii=i;ii<n;ii++) {
	if (t[ii][desp[i]]!=0) {
	  for (int j=desp[i];j<30;j++)
	    swap(t[ii][j],t[i][j]);
	  swap(indice[i],indice[ii]);
	  break;
	}
      }
      if (t[i][desp[i]]!=0) break;
    }
    if (desp[i]==30) {
      sort(base.begin(),base.end());
      return;
    }
    base.push_back(indice[i]);
    esbase[indice[i]]=1;
    for (int ii=i+1;ii<n;ii++) {
      if (t[ii][desp[i]]!=0) {
	for (int j=desp[i];j<30;j++)
	  t[ii][j]^=t[i][j];
      }
    }
  }
  sort(base.begin(),base.end());
}

int m[30][100000];

int nn;

int a[100000];
int jj[30];

void genera()
{
  for (int j=0;j<nn;j++)
    a[j]=0;
  for (int i=0;i<30;i++) {
    if (i==0) jj[i]=0;
    else jj[i]=jj[i-1]+1;
    while (jj[i]<nn and m[i][jj[i]]==0) {
      for (int ii=i;ii<30;ii++) {
	if (m[ii][jj[i]]!=0) {
	  for (int j=jj[i];j<=nn;j++)
	    swap(m[ii][j],m[i][j]);
	  break;
	}
      }
      if (m[i][jj[i]]==0) jj[i]++;
    }
    if (jj[i]<nn) {
      for (int ii=i+1;ii<30;ii++)
	if (m[ii][jj[i]]!=0)
	  for (int j=jj[i];j<=nn;j++)
	    m[ii][j]^=m[i][j];
    } else {
      for (int ii=i+1;ii<30;ii++)
	jj[ii]=nn;
      break;
    }
  }
  for (int i=29;i>=0;i--) {
    if (jj[i]==nn) {
      if (m[i][nn]!=0) {
	cout<<-1<<endl;
	exit(0);
      }
    } else {
      a[jj[i]]=m[i][nn];
      for (int j=nn-1;j>jj[i];j--)
	a[jj[i]]^=(m[i][j]&a[j]);
    }
  }
}

void obtener(int iy)
{
  for (int i=0;i<30;i++) {
    for (int j=0;j<int(base.size());j++)
      m[i][j]=((y[base[j]]&(1<<i))!=0);
    m[i][int(base.size())]=((y[iy]&(1<<i))!=0);
  }
  nn=int(base.size());
  genera();
  asigna(iy,iy);
  for (int i=0;i<int(base.size());i++)
    if (a[i])
      asigna(iy,base[i]);
}

void calcula(int iy)
{
  for (int i=0;i<30;i++) {
    for (int j=0;j<n;j++)
      m[i][j]=((x[j]&(1<<i))!=0);
    m[i][n]=((y[iy]&(1<<i))!=0);
  }
  nn=n;
  genera();
}

int main()
{
  cin>>n;
  for (int i=0;i<n;i++)
    cin>>x[i];
  for (int i=0;i<n;i++)
    cin>>y[i];
  obtenbase();
  /*
  cout<<"base:";
  for (int i=0;i<int(base.size());i++)
    cout<<base[i]<<",";
  cout<<endl;
  */
  for (int k=0;k<int(base.size());k++) {
    int i=base[k];
    calcula(i);
    if (a[i]==0) {
      int ix=-1;
      for (int j=0;j<n;j++) {
	if (a[j] and (j>i or not esbase[j])) {
	  ix=j;
	  break;
	}
      }
      asigna(i,ix);
      asigna(ix,i);
      asigna(i,ix);
      a[ix]=0;
    } else {
      a[i]=0;
    }
    for (int j=0;j<n;j++)
      if (a[j])
	asigna(i,j);
  }
  for (int i=0;i<n;i++)
    if (not esbase[i])
      obtener(i);
  cout<<int(sol.size())<<endl;
  for (int i=0;i<int(sol.size());i++)
    cout<<sol[i].first+1<<" "<<sol[i].second+1<<endl;
}