Problem:
Score : 500 points

Problem Statement

Given are N positive integers A_1,...,A_N.

Consider positive integers B_1, ..., B_N that satisfy the following condition.

Condition: For any i, j such that 1 \leq i < j \leq N, A_i B_i = A_j B_j holds.

Find the minimum possible value of B_1 + ... + B_N for such B_1,...,B_N.

Since the answer can be enormous, print the sum modulo (10^9 +7).

Constraints

1 \leq N \leq 10^4

1 \leq A_i \leq 10^6

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 ... A_N

Output

Print the minimum possible value of B_1 + ... + B_N for B_1,...,B_N that satisfy the condition, modulo (10^9 +7).

Sample Input 1

3
2 3 4

Sample Output 1

13

Let B_1=6, B_2=4, and B_3=3, and the condition will be satisfied.

Sample Input 2

5
12 12 12 12 12

Sample Output 2

5

We can let all B_i be 1.

Sample Input 3

3
1000000 999999 999998

Sample Output 3

996989508

Print the sum modulo (10^9+7).

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

use std::io::Write;
use std::collections::HashMap;
use modulo::Modulo;

#[allow(unused)]
macro_rules! debug {
    ($($format:tt)*) => (write!(std::io::stderr(), $($format)*).unwrap());
}
#[allow(unused)]
macro_rules! debugln {
    ($($format:tt)*) => (writeln!(std::io::stderr(), $($format)*).unwrap());
}

fn main() {
    let n: usize = {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).unwrap();
        let s = s.trim_right().to_owned();
        s.parse().unwrap()
    };

    let a: Vec<usize> = {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).unwrap();
        let s = s.trim_right().to_owned();
        s.split_whitespace().map(|x| x.parse().unwrap()).collect()
    };

    let primes = prime_sieve(1_000);

    let mut lcm_factor = HashMap::new();
    for &a_i in a.iter() {
        let a_i_factor = prime_factor(a_i, &primes);

        for (key, a_i_exp) in a_i_factor.iter() {
            let lcm_exp = lcm_factor.entry(*key).or_insert(0);
            if *lcm_exp < *a_i_exp {
                *lcm_exp = *a_i_exp;
            }
        }
    }

    let mut lcm = Modulo::from(1);
    for (p, exp) in lcm_factor {
        lcm = lcm * Modulo::from(p).pow(exp);
    }
    let lcm = lcm;

    let mut ans = Modulo::from(0);
    for a_i in a.iter() {
        ans = ans + lcm * Modulo::from(*a_i).inv();
    }

    println!("{}", ans.0);
}

fn prime_sieve(n: usize) -> Vec<usize> {
    let mut table: Vec<usize> = vec![0; (n + 1) as usize];
    let mut primes: Vec<usize> = Vec::new();

    for i in 2..(n+1) {
        if table[i as usize] == 0 {
            primes.push(i);
            for j in 2..n {
                if i * j > n {
                    break
                }
                table[(i * j) as usize] = 1
            }
        }
    }

    primes
}

fn prime_factor(n: usize, primes: &Vec<usize>) -> HashMap<usize, usize> {
    let mut factors = HashMap::new();

    let mut rest = n;
    for &p in primes {
        while rest % p == 0 {
            let count = factors.entry(p).or_insert(0);
            *count += 1;
            rest /= p;
        }
    }
    if rest != 1 {
        factors.insert(rest, 1);
    }

    factors
}

mod modulo {
    use std::ops::{Add, Mul, Sub, Neg};

    const MODULO: usize = 1_000_000_007;
    // const MODULO: usize = 11;

    fn positive_rem(a: isize, b: usize) -> usize {
        let b = b as isize;
        let mut value = a % b;
        if value < 0 {
            value += b;
        }
        // TODO: TryFrom
        value as usize
    }

    /// Return (x, y) s.t. ax + by = d where d = gcd(a, b)
    fn ext_gcd(a: usize, b: usize) -> (isize, isize) {
        if b == 0 {
            return (1, 0);
        }

        let q = (a / b) as isize;
        let r = a % b;
        let (x1, y1) = ext_gcd(b, r);
        (y1, x1 - q * y1)
    }

    #[derive(Debug, Copy, Clone)]
    pub struct Modulo(pub usize);

    impl From<usize> for Modulo {
        fn from(n: usize) -> Modulo {
            Modulo(n % MODULO)
        }
    }

    impl From<isize> for Modulo {
        fn from(n: isize) -> Modulo {
            // TODO: use TryFrom
            Modulo(positive_rem(n, MODULO as usize))
        }
    }

    impl From<i32> for Modulo {
        fn from(n: i32) -> Modulo {
            // TODO: use TryFrom
            Modulo(positive_rem(n as isize, MODULO as usize))
        }
    }

    impl Modulo {
        pub fn pow(self, p: usize) -> Modulo {
            if self == Modulo::from(0) {
                return Modulo::from(0);
            }
            if p == 0 {
                return Modulo::from(1);
            }

            if p % 2 == 0 {
                let half = self.pow(p / 2);
                half * half
            } else {
                self.pow(p - 1) * self
            }
        }

        // when MODULO is prime
        pub fn inv(self) -> Modulo {
            let (x, _) = ext_gcd(self.0 as usize, MODULO as usize);
            Modulo::from(x)
        }

    }

    impl Add for Modulo {
        type Output = Modulo;

        fn add(self, other: Modulo) -> Modulo {
            Modulo::from(self.0 + other.0)
        }
    }

    impl Sub for Modulo {
        type Output = Modulo;

        fn sub(self, other: Modulo) -> Modulo {
            Modulo::from(self.0 as isize - other.0 as isize)
        }
    }

    impl Mul for Modulo {
        type Output = Modulo;

        fn mul(self, other: Modulo) -> Modulo {
            Modulo::from(self.0 * other.0)
        }
    }

    impl Neg for Modulo {
        type Output = Modulo;

        fn neg(self) -> Self::Output {
            Modulo::from(0) - self
        }
    }

    impl PartialEq for Modulo {
        fn eq(&self, &other: &Self) -> bool {
            self.0 == other.0
        }
    }

    impl Eq for Modulo {}

    #[derive(Debug)]
    pub struct ModuloUtils {
        factorial: Vec<Modulo>,
        factorial_inv: Vec<Modulo>,
        inv: Vec<Modulo>,
    }

    impl ModuloUtils {
        pub fn new() -> ModuloUtils {
            ModuloUtils {
                factorial: vec![Modulo::from(1), Modulo::from(1)],
                factorial_inv: vec![Modulo::from(1), Modulo::from(1)],
                inv: vec![Modulo::from(0), Modulo::from(1)],
            }
        }

        // when MODULO is prime
        pub fn binom_coef(&mut self, n: usize, k: usize) -> Modulo {
            let len = self.factorial.len();
            if len < n + 1 {
                for i in len..(n + 1) {
                    let prev = *self.factorial.last().unwrap();
                    self.factorial.push(prev * Modulo::from(i));

                    let inv_i = - self.inv[MODULO % i] * Modulo::from(MODULO / i);
                    self.inv.push(inv_i);

                    let prev = *self.factorial_inv.last().unwrap();
                    self.factorial_inv.push(prev * self.inv[i]);
                }
            }
            self.factorial[n] * self.factorial_inv[k] * self.factorial_inv[n - k]
        }
    }

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

        #[test]
        fn eq() {
            assert_eq!(
                Modulo::from(1),
                Modulo::from((1 + MODULO) as isize)
            );
        }

        #[test]
        fn add1() {
            assert_eq!(Modulo::from(1), Modulo::from(6) + Modulo::from(6));
        }

        #[test]
        fn add2() {
            assert_eq!(Modulo::from(0), Modulo::from(5) + Modulo::from(6));
        }

        #[test]
        fn sub1() {
            assert_eq!(Modulo::from(2), Modulo::from(3) - Modulo::from(1));
        }

        #[test]
        fn sub2() {
            assert_eq!(Modulo::from(10), Modulo::from(1) - Modulo::from(2));
        }

        #[test]
        fn mul() {
            assert_eq!(Modulo::from(3), Modulo::from(5) * Modulo::from(5));
        }

        #[test]
        fn pow() {
            assert_eq!(Modulo::from(5), Modulo::from(7).pow(2));
        }

        #[test]
        fn inv() {
            assert_eq!(Modulo::from(1), Modulo::from(2) * Modulo::from(2).inv());
            assert_eq!(Modulo::from(1), Modulo::from(3) * Modulo::from(3).inv());
        }

        #[test]
        fn ext_gcd_test() {
            let a = 12isize;
            let b = 18isize;
            let (x, y) = ext_gcd(a as usize, b as usize);
            assert_eq!(6, a * x + b * y);

            let a = 4isize;
            let b = 12isize;
            let (x, y) = ext_gcd(a as usize, b as usize);
            assert_eq!(4, a * x + b * y);
        }

        #[test]
        fn binom_coef() {
            let mut modulo_utils = ModuloUtils::new();
            assert_eq!(Modulo::from(6), modulo_utils.binom_coef(4, 2));
            assert_eq!(Modulo::from(3), modulo_utils.binom_coef(3, 1));
            assert_eq!(Modulo::from(1), modulo_utils.binom_coef(3, 0));
            assert_eq!(Modulo::from(10), modulo_utils.binom_coef(5, 2));
        }
    }
}