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::io;
use std::collections::HashSet;
use std::iter::FromIterator;

fn main() {
    io::stdin().read_line(&mut String::new()).unwrap();
    let mut line0 = String::new();
    io::stdin().read_line(&mut line0).unwrap();
    let vec_a: Vec<i64> = line0
        .as_str()
        .trim()
        .split(' ')
        .map(|v| v.parse::<i64>().unwrap())
        .collect();
    let mut line1 = String::new();
    io::stdin().read_line(&mut line1).unwrap();
    let vec_b: Vec<i64> = line1
        .as_str()
        .trim()
        .split(' ')
        .map(|v| v.parse::<i64>().unwrap())
        .collect();

    print!("{}", transform_cost(&vec_a, &vec_b));
}

#[derive(Debug)]
struct Procedure {
    divisors: Vec<i64>,
}

impl PartialEq for Procedure {
    fn eq(&self, other: &Self) -> bool {
        self.divisors
            .iter()
            .zip(other.divisors.iter())
            .fold(true, |flag, (&v1, &v2)| flag && v1 == v2)
    }
}
impl Eq for Procedure {}

impl Procedure {
    fn new(divisors: &[i64]) -> Self {
        if divisors.len() == 0 {
            Procedure { divisors: vec![] }
        } else {
            Procedure {
                divisors: divisors.iter().map(|v| *v).collect(),
            }
        }
    }
}

fn transform_cost(pr1: &[i64], pr2: &[i64]) -> i64 {
    let procedures: Vec<Option<Vec<Procedure>>> = pr1.iter()
        .zip(pr2.iter())
        .map(|(a, b)| transform_steps(*a, *b))
        .collect();

    let mut k_set: HashSet<i64> = HashSet::from_iter(0..51);
    for l in (0..51).rev() {
        k_set.remove(&l);
        if !find_comb(&k_set, &procedures) {
            if l == 50 {
                return -1;
            }
            k_set.insert(l);
        }
    }
    k_set.iter().fold(0, |acc, v| acc + 2_i64.pow(*v as u32))
}

fn find_comb(k_set: &HashSet<i64>, procedures: &Vec<Option<Vec<Procedure>>>) -> bool {
    procedures.iter().fold(true, |flag, p| match p {
        &Some(ref pros) => {
            flag && pros.iter().fold(false, |flag, pro| {
                flag
                    || pro.divisors
                        .iter()
                        .fold(true, |flag, d| flag && k_set.contains(d))
            })
        }
        &None => false,
    })
}

fn transform_steps(a: i64, b: i64) -> Option<Vec<Procedure>> {
    if b > a {
        None
    } else if a == b {
        Some(vec![Procedure::new(&[])])
    } else {
        let mut procedures = Vec::<Procedure>::new();
        for k in b + 1..a + 1 {
            let r = a % k;
            if let Some(pros) = transform_steps(r, b) {
                for p in pros {
                    procedures.push(Procedure {
                        divisors: vec![k].into_iter().chain(p.divisors).collect::<Vec<i64>>(),
                    });
                }
            }
        }
        if procedures.len() > 0 {
            Some(procedures)
        } else {
            None
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_transform_steps_23_to_3() {
        let expected = vec![
            Procedure::new(&[4]),
            Procedure::new(&[5]),
            Procedure::new(&[8, 4]),
            Procedure::new(&[10]),
            Procedure::new(&[12, 4]),
            Procedure::new(&[12, 8]),
            Procedure::new(&[13, 7]),
            Procedure::new(&[14, 6]),
            Procedure::new(&[15, 5]),
            Procedure::new(&[16, 4]),
            Procedure::new(&[20]),
        ];
        let steps = transform_steps(23, 3).unwrap();
        assert!(
            expected
                .iter()
                .zip(&steps)
                .fold(true, |f, (v1, v2)| f && *v1 == *v2),
            "got {:?}",
            steps,
        );
    }

    #[test]
    fn test_transform_steps_19_to_0() {
        let steps = transform_steps(19, 0).unwrap();
        assert!(steps.len() > 1);
    }

    #[test]
    fn test_transform_steps_5_to_3() {
        assert_eq!(transform_steps(5, 3), None)
    }

    #[test]
    fn test_transform_cost_160() {
        let c = transform_cost(&[19, 10, 14], &[0, 3, 4]);
        assert_eq!(c, 160);
    }

    #[test]
    fn test_transform_cost_2() {
        let c = transform_cost(&[19, 15, 14], &[0, 0, 0]);
        assert_eq!(c, 2);
    }

    #[test]
    fn test_transform_cost_none() {
        let c = transform_cost(&[8, 13], &[5, 13]);
        assert_eq!(c, -1);
    }

    #[test]
    fn test_transform_cost_0() {
        let c = transform_cost(&[2, 0, 1, 8], &[2, 0, 1, 8]);
        assert_eq!(c, 0);
    }

    #[test]
    fn test_transform_cost_137438953472() {
        let c = transform_cost(&[50], &[13]);
        assert_eq!(c, 137438953472);
    }
}