Problem:
Score : 500 points

Problem Statement

An adult game master and N children are playing a game on an ice rink.
The game consists of K rounds.
In the i-th round, the game master announces:

Form groups consisting of A_i children each!

Then the children who are still in the game form as many groups of A_i children as possible.
One child may belong to at most one group.
Those who are left without a group leave the game. The others proceed to the next round.
Note that it's possible that nobody leaves the game in some round.

In the end, after the K-th round, there are exactly two children left, and they are declared the winners.

You have heard the values of A_1, A_2, ..., A_K. You don't know N, but you want to estimate it.

Find the smallest and the largest possible number of children in the game before the start, or determine that no valid values of N exist.

Constraints

1 \leq K \leq 10^5

2 \leq A_i \leq 10^9

All input values are integers.

Input

Input is given from Standard Input in the following format:

K
A_1 A_2 ... A_K

Output

Print two integers representing the smallest and the largest possible value of N, respectively,
or a single integer -1 if the described situation is impossible.

Sample Input 1

4
3 4 3 2

Sample Output 1

6 8

For example, if the game starts with 6 children, then it proceeds as follows:

In the first round, 6 children form 2 groups of 3 children, and nobody leaves the game.

In the second round, 6 children form 1 group of 4 children, and 2 children leave the game.

In the third round, 4 children form 1 group of 3 children, and 1 child leaves the game.

In the fourth round, 3 children form 1 group of 2 children, and 1 child leaves the game.

The last 2 children are declared the winners.

Sample Input 2

5
3 4 100 3 2

Sample Output 2

-1

This situation is impossible.
In particular, if the game starts with less than 100 children, everyone leaves after the third round.

Sample Input 3

10
2 2 2 2 2 2 2 2 2 2

Sample Output 3

2 3

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;

public static class Ex
{
    public static bool IsNullOrEmpty(this string s) { return string.IsNullOrEmpty(s); }
    public static List<string> FastSort(this List<string> s) { s.Sort(StringComparer.OrdinalIgnoreCase); return s.ToList(); }
    public static void yesno(this bool b) { Console.WriteLine(b ? "yes" : "no"); }
    public static void YesNo(this bool b) { Console.WriteLine(b ? "Yes" : "No"); }
    public static void YESNO(this bool b) { Console.WriteLine(b ? "YES" : "NO"); }
    public static int PopCount(this uint bits)
    {
        bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
        bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
        bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
        bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
        return (int)((bits & 0x0000ffff) + (bits >> 16 & 0x0000ffff));
    }
}



partial class Program
{
    public string GetStr() { return Console.ReadLine().Trim(); }
    public char GetChar() { return Console.ReadLine().Trim()[0]; }
    public int GetInt() { return int.Parse(Console.ReadLine().Trim()); }
    public long GetLong() { return long.Parse(Console.ReadLine().Trim()); }
    public double GetDouble() { return double.Parse(Console.ReadLine().Trim()); }
    public string[] GetStrArray() { return Console.ReadLine().Trim().Split(' '); }
    public string[][] GetStrArray(int N)
    {
        var res = new string[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ');
        return res;
    }
    public int[] GetIntArray() { return Console.ReadLine().Trim().Split(' ').Select(int.Parse).ToArray(); }
    public int[][] GetIntArray(int N)
    {
        var res = new int[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(int.Parse).ToArray();
        return res;
    }
    public long[] GetLongArray() { return Console.ReadLine().Trim().Split(' ').Select(long.Parse).ToArray(); }
    public long[][] GetLongArray(int N)
    {
        var res = new long[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(long.Parse).ToArray();
        return res;
    }
    public char[] GetCharArray() { return Console.ReadLine().Trim().Split(' ').Select(char.Parse).ToArray(); }
    public double[] GetDoubleArray() { return Console.ReadLine().Trim().Split(' ').Select(double.Parse).ToArray(); }
    public double[][] GetDoubleArray(int N)
    {
        var res = new double[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(double.Parse).ToArray();
        return res;
    }
    public char[][] GetGrid(int H)
    {
        var res = new char[H][];
        for (int i = 0; i < H; i++) res[i] = Console.ReadLine().Trim().ToCharArray();
        return res;
    }
    public T[] CreateArray<T>(int N, T value)
    {
        var res = new T[N];
        for (int i = 0; i < N; i++) res[i] = value;
        return res;
    }
    public T[][] CreateArray<T>(int H, int W, T value)
    {
        var res = new T[H][];
        for (int i = 0; i < H; i++)
        {
            res[i] = new T[W];
            for (int j = 0; j < W; j++) res[i][j] = value;
        }
        return res;
    }
    public T[][][] CreateArray<T>(int H, int W, int R, T value)
    {
        var res = new T[H][][];
        for (int i = 0; i < H; i++)
        {
            res[i] = new T[W][];
            for (int j = 0; j < W; j++)
            {
                res[i][j] = new T[R];
                for (int k = 0; k < R; k++) res[i][j][k] = value;
            }
        }
        return res;
    }

    Dictionary<int, List<int>> GetUnweightedAdjacencyList(int N, int M, bool isDirected, bool isNode_0indexed)
    {
        var dic = new Dictionary<int, List<int>>();
        foreach (var e in Enumerable.Range(0, N)) { dic.Add(e, new List<int>()); }
        for (int i = 0; i < M; i++)
        {
            var input = GetIntArray();
            var a = isNode_0indexed ? input[0] : input[0] - 1;
            var b = isNode_0indexed ? input[1] : input[1] - 1;
            dic[a].Add(b);
            if (isDirected == false) dic[b].Add(a);
        }
        return dic;
    }
    Dictionary<int, List<(int node, long cost)>> GetWeightedAdjacencyList(int N, int M, bool isDirected, bool isNode_0indexed)
    {
        var dic = new Dictionary<int, List<(int, long)>>();
        foreach (var e in Enumerable.Range(0, N)) { dic.Add(e, new List<(int, long)>()); }
        for (int i = 0; i < M; i++)
        {
            var input = GetIntArray();
            var a = isNode_0indexed ? input[0] : input[0] - 1;
            var b = isNode_0indexed ? input[1] : input[1] - 1;
            var c = input[2];
            dic[a].Add((b, c));
            if (isDirected == false) dic[b].Add((a, c));
        }
        return dic;
    }

    bool eq<T, U>() => typeof(T).Equals(typeof(U));
    T ct<T, U>(U a) => (T)Convert.ChangeType(a, typeof(T));
    T cv<T>(string s) => eq<T, int>() ? ct<T, int>(int.Parse(s))
                       : eq<T, long>() ? ct<T, long>(long.Parse(s))
                       : eq<T, double>() ? ct<T, double>(double.Parse(s))
                       : eq<T, char>() ? ct<T, char>(s[0])
                                         : ct<T, string>(s);
    void Multi<T>(out T a) => a = cv<T>(GetStr());
    void Multi<T, U>(out T a, out U b)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]);
    }
    void Multi<T, U, V>(out T a, out U b, out V c)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]);
    }
    void Multi<T, U, V, W>(out T a, out U b, out V c, out W d)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]);
    }
    void Multi<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]);
    }
    void Multi<T, U, V, W, X, Y>(out T a, out U b, out V c, out W d, out X e, out Y f)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]); f = cv<Y>(ar[5]);
    }

    void Swap<T>(ref T a, ref T b) { T temp = a; a = b; b = temp; }

    int[] dx = new int[] { 1, 0, -1, 0, 1, 1, -1, -1 };
    int[] dy = new int[] { 0, 1, 0, -1, 1, -1, 1, -1 };
    long mod = 1000000007;
}

class Pair : IComparable<Pair>
{
    public Pair(int _node, long _cost)
    {
        node = _node; cost = _cost;
    }
    public int node;
    public long cost;
    public int CompareTo(Pair p)
    {
        return p.cost > cost ? 1 : -1;
    }
}

class Comparable : IComparable<Comparable>
{
    public Comparable(int x, int id)
    {
        X = x;
        Id = id;
    }

    public int X;
    public int Id;
    public int CompareTo(Comparable c)
    {
        return X >= c.X ? -1 : 1;
    }
}

class Comparer<T> : IComparer<T>
{
    public int Compare(T t1, T t2)
    {
        return 1;
    }
}





partial class Program
{
    static void Main()
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Program().Solve();
        Console.Out.Flush();
        Console.Read();
    }

    public void Solve()
    {
        int K = GetInt();
        var A = GetLongArray().Reverse().ToArray();
        if (A.First() != 2)
        {
            Console.WriteLine(-1);
            return;
        }
        long min = 2;
        long max = 2;

        for(int i = 0; i < K; i++)
        {
            if ((max/A[i]>min/A[i]||(max/A[i]==min/A[i])&&min%A[i]==0)==false)
            {
                Console.WriteLine(-1);
                return;
            }
            min += (A[i] - min % A[i]) % A[i];
            max = max / A[i] * A[i] + A[i] - 1;
        }
        Console.WriteLine(min + " " + max);
    }
}