Problem:
Score : 300 points

Problem Statement

There are N monsters, numbered 1, 2, ..., N.

Initially, the health of Monster i is A_i.

Below, a monster with at least 1 health is called alive.

Until there is only one alive monster, the following is repeated:

A random alive monster attacks another random alive monster.

As a result, the health of the monster attacked is reduced by the amount equal to the current health of the monster attacking.

Find the minimum possible final health of the last monster alive.

Constraints

All values in input are integers.

2 \leq N \leq 10^5

1 \leq A_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 ... A_N

Output

Print the minimum possible final health of the last monster alive.

Sample Input 1

4
2 10 8 40

Sample Output 1

2

When only the first monster keeps on attacking, the final health of the last monster will be 2, which is minimum.

Sample Input 2

4
5 13 8 1000000000

Sample Output 2

1

Sample Input 3

3
1000000000 1000000000 1000000000

Sample Output 3

1000000000

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;

namespace abc118_c
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.ReadLine();
            var pq = new PriorityQueue<int>();
            var A = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToList();


            foreach (var a in A)
                pq.Push(-1 * a);

            int r = 0;
            while (true) 
            {
                var M1 =  pq.Top; //最弱
                pq.Pop();

                var M2 =  pq.Top; //次に弱い
                pq.Pop();

                var M0 = M2 % M1; //最弱 vs 次に弱い
                
                
                if (M0 == 0)
                {
                    //割り切れた

                    if (pq.Count == 0)
                    {
                        //最終対戦
                        r = -1 * M1;
                        break;
                    }
                    else 
                    {
                        //最終ではないなら最弱をPush
                        pq.Push(M1);
                        continue;
                    }
                }
                
                if(pq.Count == 0) 
                {
                    pq.Push(M0);
                    pq.Push(M1);
                    continue;

                }

                pq.Push(M0);

            }

            Console.WriteLine(r);
        }

        /// <summary>
        /// 優先度付き待ち行列
        /// </summary>
        /// <typeparam name="T">要素の型</typeparam>
        public class PriorityQueue<T>
          where T : IComparable<T>
        {
            #region フィールド

            public IList<T> buffer;

            #endregion
            #region 初期化

            public PriorityQueue() { this.buffer = new List<T>(); }
            public PriorityQueue(int capacity) { this.buffer = new List<T>(capacity); }

            #endregion
            #region ヒープ操作

            /// <summary>
            /// ヒープ化されている配列リストに新しい要素を追加する。
            /// </summary>
            /// <param name="array">対象の配列リスト</param>
            static void PushHeap(IList<T> array, T elem)
            {
                int n = array.Count;
                array.Add(elem);

                while (n != 0)
                {
                    int i = (n - 1) / 2;
                    if (array[n].CompareTo(array[i]) > 0)
                    {
                        T tmp = array[n]; array[n] = array[i]; array[i] = tmp;
                    }
                    n = i;
                }
            }

            /// <summary>
            /// ヒープから最大値を削除する。
            /// </summary>
            /// <param name="array">対象の配列リスト</param>
            static void PopHeap(IList<T> array)
            {
                int n = array.Count - 1;
                array[0] = array[n];
                array.RemoveAt(array.Count - 1);

                for (int i = 0, j; (j = 2 * i + 1) < n;)
                {
                    if ((j != n - 1) && (array[j].CompareTo(array[j + 1]) < 0))
                        j++;
                    if (array[i].CompareTo(array[j]) < 0)
                    {
                        T tmp = array[j]; array[j] = array[i]; array[i] = tmp;
                    }
                    i = j;
                }
            }

            #endregion
            #region 要素の挿入・削除

            /// <summary>
            /// 要素のプッシュ。
            /// </summary>
            /// <param name="elem">挿入したい要素</param>
            public void Push(T elem)
            {
                PushHeap(this.buffer, elem);
            }

            /// <summary>
            /// 要素を1つポップ。
            /// </summary>
            /// <remarks>
            /// 今回の実装では、先頭要素の読み出しと削除は別に行う。
            /// この Pop では削除のみ。
            /// 読み出しには Top プロパティを使う。
            /// </remarks>
            public void Pop()
            {
                PopHeap(this.buffer);
            }

            /// <summary>
            /// 先頭要素の読み出し。
            /// </summary>
            public T Top
            {
                get { return this.buffer[0]; }
            }

            public int Count
            {
                get { return this.buffer.Count; }
            }

            #endregion
        }

    }
}