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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using E = System.Linq.Enumerable;


class Program
{
    static Dictionary<long, long> dic = new Dictionary<long, long>();
    static long mod = 1000000007;
    static void Main(string[] args)
    {
        var N = long.Parse(Console.ReadLine());
        var A = Console.ReadLine().Split(' ').Select(x => long.Parse(x)).ToArray();

        //全体の最小公倍数
        var lcm = new Modular(1);
        //Factorization(7);
        for (int i = 0; i < N; i++)
        {
            Factorization(A[i]);
        }

        foreach (var item in dic)
        {
            lcm *= Modular.Pow(new Modular(item.Key), (int)item.Value).value;
        }

        var ans = new Modular(0);
        for (int i = 0; i < N; i++)
        {
            ans += lcm / new Modular(A[i]);
        }

        Console.WriteLine(ans.value%mod);
    }

    static void Factorization(long N)
    {
        int i = 2;
        var tmp = N;
        var count = 0;
        while (i * i <= N)
        {
            if (tmp % i == 0)
            {
                tmp /= i;
                count++;
                
            }
            else
            {
                if (dic.ContainsKey(i))
                {
                    if (dic[i] < count)
                    {
                        dic[i] = count;
                    }
                }
                else if(count > 0)
                {
                    dic.Add(i, count);
                }
                i++;
                count = 0;
            }
        }

        if(tmp > 1)
        {
            if (!dic.ContainsKey(tmp))
            {
                dic.Add(tmp,1);
            }
        }


    }
}

public static class CharExt
{
    public static int ToInt(this char self)
    {
        return self - '0';
    }
}


class Modular
{
    private const int M = 1000000007;
    public long value;
    public Modular(long value) { this.value = value; }
    public static implicit operator Modular(long a)
    {
        var m = a % M;
        return new Modular((m < 0) ? m + M : m);
    }
    public static Modular operator +(Modular a, Modular b)
    {
        return (a.value + b.value)%M;
    }
    public static Modular operator -(Modular a, Modular b)
    {
        return a.value - b.value;
    }
    public static Modular operator *(Modular a, Modular b)
    {
        return a.value * b.value;
    }
    public static Modular Pow(Modular a, int n)
    {
        switch (n)
        {
            case 0:
                return 1;
            case 1:
                return a;
            default:
                var p = Pow(a, n / 2);
                return p * p * Pow(a, n % 2);
        }
    }
    public static Modular operator /(Modular a, Modular b)
    {
        return a * Pow(b, M - 2);
    }
    private static readonly List<int> facs = new List<int> { 1 };
    private static Modular Fac(int n)
    {
        for (int i = facs.Count; i <= n; ++i)
        {
            facs.Add((int)(Math.BigMul(facs.Last(), i) % M));
        }
        return facs[n];
    }
    public static Modular Ncr(int n, int r)
    {
        return (n < r) ? 0
             : (n == r) ? 1
                        : Fac(n) / (Fac(r) * Fac(n - r));
    }
    public static explicit operator int(Modular a)
    {
        return (int)a.value;
    }

    public static Modular Lcm(Modular a, Modular b)
    {
        var tmp = Gcdl(a.value, b.value);
        return ((a * b) / new Modular(tmp));
    }
    static Modular Gcd(Modular m, Modular n)
    {
        if (n.value > m.value) return Gcd(n,m);
        if (n.value == 0) return m;
        var r = new Modular(m.value % n.value);
        return Gcd(n,r);
    }

    static long Gcdl(long m, long n)
    {
        if (n > m) return Gcdl(n,m);
        if (n == 0) return m;
        return Gcdl(n, m % n);
    }
}
public class PriorityQueue<T> : IEnumerable<T>
{
    private readonly List<T> _data = new List<T>();
    private readonly IComparer<T> _comparer;
    private readonly bool _isDescending;

    public PriorityQueue(IComparer<T> comparer, bool isDescending = true)
    {
        _comparer = comparer;
        _isDescending = isDescending;
    }

    public PriorityQueue(Comparison<T> comparison, bool isDescending = true)
        : this(Comparer<T>.Create(comparison), isDescending)
    {
    }

    public PriorityQueue(bool isDescending = true)
        : this(Comparer<T>.Default, isDescending)
    {
    }

    public void Enqueue(T item)
    {
        _data.Add(item);
        var childIndex = _data.Count - 1;
        while (childIndex > 0)
        {
            var parentIndex = (childIndex - 1) / 2;
            if (Compare(_data[childIndex], _data[parentIndex]) >= 0)
                break;
            Swap(childIndex, parentIndex);
            childIndex = parentIndex;
        }
    }

    public T Dequeue()
    {
        var lastIndex = _data.Count - 1;
        var firstItem = _data[0];
        _data[0] = _data[lastIndex];
        _data.RemoveAt(lastIndex--);
        var parentIndex = 0;
        while (true)
        {
            var childIndex = parentIndex * 2 + 1;
            if (childIndex > lastIndex)
                break;
            var rightChild = childIndex + 1;
            if (rightChild <= lastIndex && Compare(_data[rightChild], _data[childIndex]) < 0)
                childIndex = rightChild;
            if (Compare(_data[parentIndex], _data[childIndex]) <= 0)
                break;
            Swap(parentIndex, childIndex);
            parentIndex = childIndex;
        }
        return firstItem;
    }

    public T Peek()
    {
        return _data[0];
    }

    private void Swap(int a, int b)
    {
        var tmp = _data[a];
        _data[a] = _data[b];
        _data[b] = tmp;
    }

    private int Compare(T a, T b)
    {
        return _isDescending ? _comparer.Compare(b, a) : _comparer.Compare(a, b);
    }

    public int Count => _data.Count;

    public IEnumerator<T> GetEnumerator()
    {
        return _data.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}


class UnionFind



{



    // 親要素のインデックスを保持する



    // 親要素が存在しない(自身がルートである)とき、マイナスでグループの要素数を持つ



    public long[] Parents { get; set; }



    public UnionFind(long n)



    {



        this.Parents = new long[n];



        for (int i = 0; i < n; i++)



        {



            // 初期状態ではそれぞれが別のグループ(ルートは自分自身)



            // ルートなのでマイナスで要素数(1個)を保持する



            this.Parents[i] = -1;



        }



    }







    // 要素xのルート要素はどれか



    public long Find(long x)



    {



        // 親がマイナスの場合は自分自身がルート



        if (this.Parents[x] < 0) return x;



        // ルートが見つかるまで再帰的に探す



        // 見つかったルートにつなぎかえる



        this.Parents[x] = Find(this.Parents[x]);



        return this.Parents[x];



    }







    // 要素xの属するグループの要素数を取得する



    public long Size(long x)



    {



        // ルート要素を取得して、サイズを取得して返す



        return -this.Parents[this.Find(x)];



    }







    // 要素x, yが同じグループかどうか判定する



    public bool Same(long x, long y)



    {



        return this.Find(x) == this.Find(y);



    }







    // 要素x, yが属するグループを同じグループにまとめる



    public bool Union(long x, long y)



    {



        // x, y のルート



        x = this.Find(x);



        y = this.Find(y);



        // すでに同じグループの場合処理しない



        if (x == y) return false;







        // 要素数が少ないグループを多いほうに書き換えたい



        if (this.Size(x) < this.Size(y))



        {



            var tmp = x;



            x = y;



            y = tmp;



        }



        // まとめる先のグループの要素数を更新



        this.Parents[x] += this.Parents[y];



        // まとめられるグループのルートの親を書き換え



        this.Parents[y] = x;



        return true;



    }



}