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: Wrong Answer)

fn read_line() -> String {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim().to_owned()
}

fn reads<T>() -> Vec<T>
where
    T: std::str::FromStr,
    <T as std::str::FromStr>::Err: std::fmt::Debug,
{
    read_line()
        .split_whitespace()
        .map(|w| w.parse().unwrap())
        .collect()
}

struct XorShift {
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}

impl XorShift {
    fn new(seed: u32) -> XorShift {
        let mut ret = XorShift {
            x: 123456789,
            y: 362436069,
            z: 521288629,
            w: 88675123 ^ seed,
        };
        for _ in 0..16 {
            ret.gen();
        }
        ret
    }

    fn gen(&mut self) -> u32 {
        let t = self.x ^ (self.x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        self.w = (self.w ^ (self.w >> 19)) ^ (t ^ (t >> 8));
        self.w
    }

    fn gen_u32(&mut self, low: u32, high: u32) -> u32 {
        assert!(high > low);
        let r = high - low;
        let v = self.gen();
        low + (v % r)
    }

    fn gen_f64(&mut self) -> f64 {
        // let a = ((self.gen() as u64) << 32) + self.gen() as u64;
        // a as f64 / 0xFFFF_FFFF_FFFF_FFFFu64 as f64
        self.gen() as f64 / 0xFFFF_FFFFu32 as f64
    }
}

fn solve(from: u32, to: u32, hist: &mut Vec<u32>, moves: &mut Vec<Vec<u32>>) {
    if from == to {
        // println!("* {:?}", hist);

        for i in 0..hist.len() {
            if i + 1 < hist.len() {
                assert!(hist[i] > hist[i + 1]);
            }
        }
        moves.push(hist.clone());

        return;
    }

    if from < to {
        return;
    }

    for i in 1..from {
        hist.push(i);
        solve(from % i, to, hist, moves);
        hist.pop();
    }
}

fn score(movess: &Vec<Vec<Vec<u32>>>, choice: &Vec<usize>) -> u64 {
    let mut arr = [false; 51];

    for i in 0..choice.len() {
        let c = choice[i];
        for j in 0..movess[i][c].len() {
            arr[movess[i][c][j] as usize] = true;
        }
    }

    let mut ret = 0;
    for i in 0..51 {
        if arr[i] {
            ret += 1 << i;
        }
    }
    ret
}

use std::io::Write;

fn main() {
    // for i in 0..50 {
    //     for j in 0..50 {
    //         if i < j {
    //             continue;
    //         }
    //         let mut hist = vec![];
    //         let mut moves = vec![];
    //         solve(i, j, &mut hist, &mut moves);

    //         println!("{} -> {}: {}", i, j, moves.len());
    //     }
    // }

    let n = reads()[0];

    let aa: Vec<u32> = reads();
    let bb: Vec<u32> = reads();

    let mut movess: Vec<Vec<Vec<u32>>> = vec![];

    for i in 0..n {
        let mut hist = vec![];
        let mut moves = vec![];
        solve(aa[i], bb[i], &mut hist, &mut moves);
        if moves.len() == 0 {
            println!("-1");
            return;
        }
        movess.push(moves);
    }

    let mut rng = XorShift::new(777);

    let mut choice = vec![0; n];
    for i in 0..n {
        choice[i] = rng.gen_u32(0, movess[i].len() as u32) as usize;
    }

    let mut cur_score = score(&movess, &choice);
    let mut best_score = cur_score;
    // let mut best_ans = choice.clone();

    let mut temp = (cur_score as f64) / 10.0;
    const DECAY: f64 = 0.9999999;

    while temp > 0.01 {
        temp *= DECAY;

        // let ix = rng.gen_u32(0, k as u32) as usize;
        // let ty = rng.gen_u32(0, 2);

        let ix = rng.gen_u32(0, n as u32) as usize;
        let to = rng.gen_u32(0, movess[ix].len() as u32) as usize;
        let bkup = choice[ix];
        choice[ix] = to;

        let next_score = score(&movess, &choice);

        if next_score <= cur_score
            || ((cur_score - next_score) as f64 / temp).exp() >= rng.gen_f64()
        {
            cur_score = next_score;
            if best_score > cur_score {
                best_score = cur_score;
                // best_ans = choice.clone();

                writeln!(
                    &mut std::io::stderr(),
                    "Score: {}, temp: {}",
                    best_score,
                    temp
                ).unwrap();
            }
        } else {
            choice[ix] = bkup;
        }
    }

    println!("{}", best_score);

    // writeln!(
    //     &mut std::io::stderr(),
    //     "Best score: {}, improve: {}, approx: {}",
    //     best_score,
    //     (init_score - best_score),
    //     (init_score - best_score) as f64 / 100.0 * 30.0
    // ).unwrap();

    // for (f, t) in best_swaps {
    //     println!("{} {} {} {}", data[f].1, data[f].0, data[t].1, data[t].0);
    // }
}