#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
using vll = vector<long long>;
using vpii = vector<pair<int, int>>;
using vpll = vector<pair<long long, long long>>;
using ti3 = tuple<int, int, int>;
using vti3 = vector<ti3>;
template <class T, int s>
using va = vector<array<T, s>>;
template <class T, class T2>
using umap = unordered_map<T, T2>;
template <class T>
using uset = unordered_set<T>;
template <class T, class S>
void cmin(T &a, const S &b) {
  if (a > b) a = b;
}
template <class T, class S>
void cmax(T &a, const S &b) {
  if (a < b) a = b;
}
const long long mod = 1000000007;
template <class T>
using heap = priority_queue<T, vector<T>, greater<T>>;
template <class T>
using pque = priority_queue<T, vector<T>, function<T(T, T)>>;
template <class T>
inline void hash_combine(size_t &seed, const T &v) {
  hash<T> hasher;
  seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
namespace std {
template <typename S, typename T>
struct hash<pair<S, T>> {
  inline size_t operator()(const pair<S, T> &v) const {
    size_t seed = 0;
    hash_combine(seed, v.first);
    hash_combine(seed, v.second);
    return seed;
  }
};
template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
struct HashValueImpl {
  static void apply(size_t &seed, Tuple const &tuple) {
    HashValueImpl<Tuple, Index - 1>::apply(seed, tuple);
    hash_combine(seed, std::get<Index>(tuple));
  }
};
template <class Tuple>
struct HashValueImpl<Tuple, 0> {
  static void apply(size_t &seed, Tuple const &tuple) {
    hash_combine(seed, std::get<0>(tuple));
  }
};
template <typename... TT>
struct hash<std::tuple<TT...>> {
  size_t operator()(std::tuple<TT...> const &tt) const {
    size_t seed = 0;
    HashValueImpl<std::tuple<TT...>>::apply(seed, tt);
    return seed;
  }
};
}  // namespace std
template <class T>
int id(vector<T> &a, T b) {
  return lower_bound(a.begin(), a.end(), b) - a.begin();
}
long long pow(long long base, long long i, long long mod) {
  long long a = 1;
  while (i) {
    if (i & 1) {
      a *= base;
      a %= mod;
    }
    base *= base;
    base %= mod;
    i /= 2;
  }
  return a;
}
long long gcd(long long a, long long b) {
  while (b) {
    long long c = a % b;
    a = b;
    b = c;
  }
  return a;
}
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }
int popcnt(unsigned long long a) { return __builtin_popcountll(a); }
class unionfind {
  vector<int> par, rank, size_;

 public:
  unionfind(int n) : par(n), rank(n), size_(n, 1) {
    iota(par.begin(), par.end(), 0);
  }
  int find(int x) {
    if (par[x] == x) return x;
    return par[x] = find(par[x]);
  }
  void unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) swap(x, y);
    par[y] = x;
    size_[x] += size_[y];
    if (rank[x] == rank[y]) rank[x]++;
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return size_[find(x)]; }
};
template <class T, class Func = function<T(T, T)>>
class segtree {
  vector<T> obj;
  int offset;
  Func updater;
  T e;
  int bufsize(int num) {
    int i = 1;
    for (; num > i; i <<= 1)
      ;
    offset = i - 1;
    return (i << 1) - 1;
  }
  T query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l) return e;
    if (a <= l && r <= b)
      return obj[k];
    else
      return updater(query(a, b, k * 2 + 1, l, (l + r) / 2),
                     query(a, b, k * 2 + 2, (l + r) / 2, r));
  }

 public:
  T query(int a, int b) { return query(a, b, 0, 0, offset + 1); }
  void updateall(int l = 0, int r = -1) {
    if (r < 0) r = offset + 1;
    l += offset, r += offset;
    if (l == 0) return;
    do {
      l = l - 1 >> 1, r = r - 1 >> 1;
      for (int i = l; i < r; i++)
        obj[i] = updater(obj[i * 2 + 1], obj[i * 2 + 2]);
    } while (l);
  }
  void update(int k, T &a) {
    k += offset;
    obj[k] = a;
    while (k) {
      k = k - 1 >> 1;
      obj[k] = updater(obj[k * 2 + 1], obj[k * 2 + 2]);
    }
  }
  segtree(int n, T e, const Func &updater = Func())
      : obj(bufsize(n), e), e(e), updater(updater) {}
  segtree(vector<T> &vec, T e, const Func &updater = Func())
      : obj(bufsize(vec.size()), e), e(e), updater(updater) {
    copy(vec.begin(), vec.end(), obj.begin() + offset);
    updateall();
  }
  T &operator[](int n) { return obj[n + offset]; }
};
template <class T = int>
class BIT {
  vector<T> bit;

 public:
  BIT(int n) : bit(n + 1, 0) {}
  void add(int i, T x) {
    while (i <= bit.size()) {
      bit[i] += x;
      i += i & -i;
    }
  }
  T sum(int i) {
    T s = 0;
    while (i) {
      s += bit[i];
      i &= i - 1;
    }
    return s;
  }
};
template <class T>
class rangeadd {
  BIT<T> b0, b1;
  rangeadd(int n) : b0(n), b1(n) {}
  void add(int l, int r, T x) {
    b0.add(l, -x(l - 1));
    b1.add(l, x);
    b0.add(r, x * r);
    b1.add(r, -x);
  }
  T sum(int i) { return b0.sum(i) + b1.sum(i) * i; }
};
int main() {
  int n;
  cin >> n;
  vi a(n), b(n);
  for (int i = 0; i < n; i++) cin >> a[i];
  for (int i = 0; i < n; i++) cin >> b[i];
  int x = 0;
  for (int i = 0; i < n; i++) x ^= a[i];
  int ans = 0;
  int f = 0;
  {
    umap<int, int> a2;
    for (int i = 0; i < n; i++) a2[a[i]]++;
    a2[x]++;
    if (a2[x] > 1) f = 1;
    for (int i = 0; i < n; i++) a2[b[i]]--;
    for (auto x : a2) {
      if (x.second < 0) {
        cout << -1 << endl;
        return 0;
      }
    }
  }
  umap<int, multimap<int, int>> m;
  vector<multimap<int, int>::iterator> m2(n);
  for (int i = 0; i < n; i++)
    if (a[i] != b[i]) m2[i] = m[a[i]].emplace(b[i], i);
  for (int i = 0; i < n; i++) {
    if (a[i] == b[i]) continue;
    if (m[b[i]].find(a[i]) != m[b[i]].end()) {
      ans += 3;
      if (f && (a[i] == x || b[i] == x)) ans--, f--;
      auto p = m[b[i]].find(a[i]);
      auto o = *p;
      m[a[i]].erase(m2[i]);
      m[b[i]].erase(p);
      swap(b[i], b[o.second]);
    } else {
      ans++;
      m[a[i]].erase(m2[i]);
    }
  }
  cout << ans << endl;
}
