Problem:
Score : 1000 points

Problem Statement

There is a sequence of length N: a = (a_1, a_2, ..., a_N).
Here, each a_i is a non-negative integer.

Snuke can repeatedly perform the following operation:

Let the XOR of all the elements in a be x. Select an integer i (1 ≤ i ≤ N) and replace a_i with x.

Snuke's objective is to match a with another sequence b = (b_1, b_2, ..., b_N).
Here, each b_i is a non-negative integer.

Determine whether the objective is achievable, and find the minimum necessary number of operations if the answer is positive.

Constraints

2 ≤ N ≤ 10^5

a_i and b_i are integers.

0 ≤ a_i, b_i < 2^{30}

Input

Input is given from Standard Input in the following format:

N
a_1 a_2 ... a_N
b_1 b_2 ... b_N

Output

If the objective is achievable, print the minimum necessary number of operations.
Otherwise, print -1 instead.

Sample Input 1

3
0 1 2
3 1 0

Sample Output 1

2

At first, the XOR of all the elements of a is 3.
If we replace a_1 with 3, a becomes (3, 1, 2).

Now, the XOR of all the elements of a is 0.
If we replace a_3 with 0, a becomes (3, 1, 0), which matches b.

Sample Input 2

3
0 1 2
0 1 2

Sample Output 2

0

Sample Input 3

2
1 1
0 0

Sample Output 3

-1

Sample Input 4

4
0 1 2 3
1 0 3 2

Sample Output 4

5

Solution in Rust (1.15.1) (judge verdict: Wrong Answer)

// use std::ops::{Index, IndexMut};
// use std::cmp::{Ordering, min, max};
// use std::collections::{BinaryHeap, BTreeMap};
// use std::collections::btree_map::Entry::{Occupied, Vacant};
// use std::clone::Clone;

fn getline() -> String{
    let mut res = String::new();
    std::io::stdin().read_line(&mut res).ok();
    res
}

macro_rules! readl {
    ($t: ty) => {
        {
            let s = getline();
            s.trim().parse::<$t>().unwrap()
        }
    };
    ($( $t: ty),+ ) => {
        {
            let s = getline();
            let mut iter = s.trim().split(' ');
            ($(iter.next().unwrap().parse::<$t>().unwrap(),)*) 
        }
    };
}

macro_rules! readlvec {
    ($t: ty) => {
        {
            let s = getline();
            let iter = s.trim().split(' ');
            iter.map(|x| x.parse().unwrap()).collect::<Vec<$t>>()
        }
    }
}

macro_rules! mvec {
    ($v: expr, $s: expr) => {
        vec![$v; $s]
    };
    ($v: expr, $s: expr, $($t: expr),*) => {
        vec![mvec!($v, $($t),*); $s]
    };
}

macro_rules! debug {
    ($x: expr) => {
        println!("{}: {:?}", stringify!($x), $x)
    }
}

fn printiter<'a, T>(v: &'a T)
where
    &'a T: std::iter::IntoIterator, 
    <&'a T as std::iter::IntoIterator>::Item: std::fmt::Display {
    for (i,e) in v.into_iter().enumerate() {
        if i != 0 {
            print!(" ");
        }
        print!("{}", e);
    }
    println!("");
}

struct UnionFind {
    par: Vec<usize>,
    rank: Vec<usize>,
    cnt: Vec<u32>,
}

impl UnionFind {
    fn new(n: usize) -> UnionFind {
        let mut vec = vec![0;n];
        for i in 0..n {
            vec[i] = i;
        }
        UnionFind {
            par : vec,
            rank : vec![0;n],
            cnt : vec![0;n],
        }
    }

    fn find(&mut self, x: usize) -> usize {
        if x == self.par[x] {
            x
        }else{
            let par = self.par[x];
            let res = self.find(par);
            self.par[x] = res;
            res
        }
    }

    fn same(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }

    fn unite(&mut self, a: usize, b: usize){
        let apar = self.find(a);
        let bpar = self.find(b);
        if apar == bpar {
            return;
        }
        if self.rank[apar] > self.rank[bpar] {
            self.par[bpar] = apar;
            self.cnt[apar] += self.cnt[bpar];
        }else{
            self.par[apar] = bpar;
            self.cnt[bpar] += self.cnt[apar];
            if self.rank[apar] == self.rank[bpar] {
                self.rank[bpar] += 1;
            }
        }
    }

    fn count(&mut self, v: usize) -> u32 {
        let par = self.find(v);
        self.cnt[par]
    }

    fn add(&mut self, v: usize, x: u32) {
        let par = self.find(v);
        self.cnt[par] += 1;
    }
}

fn main() {
    let n = readl!(usize);
    let a = readlvec!(i32);
    let b = readlvec!(i32);
    let axor = a.iter().fold(0, |sum, &x| sum^x);
    let mut acnt = std::collections::HashMap::new();
    for &e in &a {
        let x = acnt.entry(e).or_insert(0);
        *x += 1;
    }
    let mut ex = true;
    let mut usea = false;
    // let mut cnt = 0;
    for i in 0..n {
        if a[i] != b[i] {
            // cnt += 1;
            if axor == b[i] && !usea {
                usea = true;
            } else {
                let x = acnt.entry(b[i]).or_insert(0);
                if *x == 0 {
                    ex = false;
                    break;
                }
                *x -= 1;
            }
        }
    }
    if !ex {
        println!("-1");
        return;
    }
    
    use std::collections::BTreeSet;
    let mut za = a.clone();
    za.push(axor);
    za.sort();
    let za: Vec<_> = za.into_iter().collect::<BTreeSet<_>>().into_iter().collect();
    let mut uf = UnionFind::new(za.len());
    for (&a, &b) in a.iter().zip(b.iter()) {
        let ap = za.binary_search(&a).unwrap();
        let bp = za.binary_search(&b).unwrap();
        // debug!(ap); debug!(bp);
        uf.unite(ap, bp);
        uf.add(ap, 1);
    }
    uf.add(za.binary_search(&axor).unwrap(), 1);
    // debug!(uf.cnt);

    let mut used = vec![false; za.len()];
    let mut ans = 0;
    for i in 0..za.len() {
        let par = uf.find(i);
        // debug!(par);
        if !used[par] {
            used[par] = true;
            let num = uf.count(i);
            // debug!(num);
            if num > 1 {
                ans += num+1;
            }
        }
        // debug!(ans);
    }
    if usea {
        println!("{}", ans-2);
    } else {
        println!("{}", ans);
    }
}