Problem:
Score : 700 points

Problem Statement

Aoki is playing with a sequence of numbers a_{1}, a_{2}, ..., a_{N}. Every second, he performs the following operation :

Choose a positive integer k. For each element of the sequence v, Aoki may choose to replace v with its remainder when divided by k, or do nothing with v. The cost of this operation is 2^{k} (regardless of how many elements he changes).

Aoki wants to turn the sequence into b_{1}, b_{2}, ..., b_{N} (the order of the elements is important). Determine if it is possible for Aoki to perform this task and if yes, find the minimum cost required.

Constraints

1 \leq N \leq 50

0 \leq a_{i}, b_{i} \leq 50

All values in the input are integers.

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

Print the minimum cost required to turn the original sequence into b_{1}, b_{2}, ..., b_{N}. If the task is impossible, output -1 instead.

Sample Input 1

3
19 10 14
0 3 4

Sample Output 1

160

Here's a possible sequence of operations :

Choose k = 7. Replace 19 with 5, 10 with 3 and do nothing to 14. The sequence is now 5, 3, 14.

Choose k = 5. Replace 5 with 0, do nothing to 3 and replace 14 with 4. The sequence is now 0, 3, 4.

The total cost is 2^{7} + 2^{5} = 160.

Sample Input 2

3
19 15 14
0 0 0

Sample Output 2

2

Aoki can just choose k = 1 and turn everything into 0. The cost is 2^{1} = 2.

Sample Input 3

2
8 13
5 13

Sample Output 3

-1

The task is impossible because we can never turn 8 into 5 using the given operation.

Sample Input 4

4
2 0 1 8
2 0 1 8

Sample Output 4

0

Aoki doesn't need to do anything here. The cost is 0.

Sample Input 5

1
50
13

Sample Output 5

137438953472

Beware of overflow issues.

Solution in Rust (1.15.1) (judge verdict: Accepted)

use std::cmp;
use std::collections::BTreeSet;


const MAX_D: usize = 50;
const MAX_COST: usize = 1 << 55;

fn main() {
    let mut sc = Scanner::new();
    let n: usize = sc.read();
    let a: Vec<usize> = (0..n).map(|_| sc.read()).collect();
    let b: Vec<usize> = (0..n).map(|_| sc.read()).collect();

    let mut ans: Vec<usize> = Vec::new();
    for upper in (1..(MAX_D + 2)).rev() {
        let mut costs = vec![vec![MAX_COST; MAX_D + 1]; MAX_D + 1];

        for d in 1..upper {
            for from in 0..(MAX_D + 1) {
                let to = from % d;
                costs[from][to] = (1 << d);
            }
        }

        for d in &ans {
            let d = *d;
            for from in 0..(MAX_D + 1) {
                let to = from % d;
                costs[from][to] = (1 << d);
            }
        }

        for i in 0..(MAX_D + 1) {
            costs[i][i] = 0;
        }

        for k in 0..(MAX_D + 1) {
            for i in 0..(MAX_D + 1) {
                for j in 0..(MAX_D + 1) {
                    costs[i][j] = cmp::min(costs[i][j], costs[i][k] + costs[k][j]);
                }
            }
        }

        let mut check = true;
        for i in 0..n {
            if costs[a[i]][b[i]] == MAX_COST {
                check = false;
            }
        }
        if !check {
            if upper == MAX_D + 1 {
                println!("-1");
                return;
            }
            ans.push(upper);
        }
    }

    let mut cost: usize = 0;
    for a in &ans {
        cost += (1 << *a);
    }
    println!("{}", cost);
}

struct Scanner {
    ptr: usize,
    length: usize,
    buf: Vec<u8>,
    small_cache: Vec<u8>,
}

impl Scanner {
    fn new() -> Scanner {
        Scanner { ptr: 0, length: 0, buf: vec![0; 1024], small_cache: vec![0; 1024] }
    }

    fn load(&mut self) {
        use std::io::Read;
        let mut s = std::io::stdin();
        self.length = s.read(&mut self.buf).unwrap();
    }

    fn byte(&mut self) -> u8 {
        if self.ptr >= self.length {
            self.ptr = 0;
            self.load();
            if self.length == 0 {
                self.buf[0] = b'\n';
                self.length = 1;
            }
        }

        self.ptr += 1;
        return self.buf[self.ptr - 1];
    }

    fn is_space(b: u8) -> bool { b == b'\n' || b == b'\r' || b == b'\t' || b == b' ' }

    fn read<T>(&mut self) -> T where T: std::str::FromStr, T::Err: std::fmt::Debug, {
        let mut b = self.byte();
        while Scanner::is_space(b) {
            b = self.byte();
        }

        for pos in 0..self.small_cache.len() {
            self.small_cache[pos] = b;
            b = self.byte();
            if Scanner::is_space(b) {
                return String::from_utf8_lossy(&self.small_cache[0..(pos + 1)]).parse().unwrap();
            }
        }

        let mut v = self.small_cache.clone();
        while !Scanner::is_space(b) {
            v.push(b);
            b = self.byte();
        }
        return String::from_utf8_lossy(&v).parse().unwrap();
    }
}