Problem:
Score : 200 points

Problem Statement

An X-layered kagami mochi (X ≥ 1) is a pile of X round mochi (rice cake) stacked vertically where each mochi (except the bottom one) has a smaller diameter than that of the mochi directly below it. For example, if you stack three mochi with diameters of 10, 8 and 6 centimeters from bottom to top in this order, you have a 3-layered kagami mochi; if you put just one mochi, you have a 1-layered kagami mochi.

Lunlun the dachshund has N round mochi, and the diameter of the i-th mochi is d_i centimeters. When we make a kagami mochi using some or all of them, at most how many layers can our kagami mochi have?

Constraints

1 ≤ N ≤ 100

1 ≤ d_i ≤ 100

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
d_1
:
d_N

Output

Print the maximum number of layers in a kagami mochi that can be made.

Sample Input 1

4
10
8
8
6

Sample Output 1

3

If we stack the mochi with diameters of 10, 8 and 6 centimeters from bottom to top in this order, we have a 3-layered kagami mochi, which is the maximum number of layers.

Sample Input 2

3
15
15
15

Sample Output 2

1

When all the mochi have the same diameter, we can only have a 1-layered kagami mochi.

Sample Input 3

7
50
30
50
100
50
80
30

Sample Output 3

4

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

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Globalization;
using System.Numerics;
using System.Text.RegularExpressions;
//byte 255 int<2147483647 ≒ 2 * 10^9 long < 9223372036854775807 ≒ 9 * 10^18
//decimal 29桁

class Myon
{
    //chokudaiさんのコードをコピペ
    static Scanner cin;
    public Myon() { }
    public static int Main()
    {
        //Console.SetOut(new Printer(Console.OpenStandardOutput()));
        cin = new Scanner();
        new Myon().calc();

        return 0;
    }

    public void calc()
    {
        int n = cin.nextInt();
        int[] d = cin.nextIntArr(n);
        List<int> d2 = new List<int>(d);
        d2 = d2.Distinct().ToList();
        int ans = d2.Count();
        showL(ans);

    }

    public void calc_ABC076D()
    {
        int n = cin.nextInt();
        int[] t = new int[n + 1]; for (int i = 0; i < n; i++) t[i] = cin.nextInt();
        int[] v = new int[n + 1]; for (int i = 0; i < n; i++) v[i] = cin.nextInt();
        t[n] = 0; v[n] = 0;

        //k番目の拘束条件(t = Σti(i=0 ~ k-1) ~ Σti + tk) Σti(i=0 ~ k-1) を stk とかく
        //          (言い換えればk番目の拘束が始まる時間)
        //  は、言い換えればt = x において (v(x)を実際の速度として) 
        //  x <= stk-1 ⇒ v(x) <= vk + (stk-1 + x) 
        //  x >= stk ⇒ v(x) ∈ [vk - (stk - x), vk + (stk + x) ]

        int[] sumt = new int[n+2]; for (int i = 1; i < n + 2; i++) sumt[i] = sumt[i - 1] + t[i-1];
        int[] maxv = new int[sumt[n+1]+1];

        for(int tt = 1; tt < sumt[n+1]; tt++) 
        {
            maxv[tt] = maxv[tt - 1] + 1;
            for(int i = 0; i < n+1; i++)
            {
                if (tt <= sumt[i]) maxv[tt] = Math.Min(maxv[tt], v[i] + (sumt[i] - tt));
                else if( tt <= sumt[i] + t[i]) maxv[tt] = Math.Min(maxv[tt], v[i]);
            }
        }

        double ans = 0;
        int imadokonokousoku = 0;
        int tempt = 1;
        for (int tt = 1; tt < sumt[n]; tt++)
        {
            if(tempt == t[imadokonokousoku]) { tempt = 0; imadokonokousoku++; }
            ans += ((double)maxv[tt] + maxv[tt - 1]) / 2;
            if (maxv[tt] < v[imadokonokousoku] &&  maxv[tt] == maxv[tt + 1])
            {
                ans += 0.25;//t= a.5 に最大値がくる場合の補正
            }
            tempt++;
        }
        ans += 0.5;//最後の一秒 v = 1 to 0なので
        showL(ans);

    }
    public void calcC()
    {
        int n = cin.nextInt();

        //System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        //sw.Start();

        int m = cin.nextInt();
        List<int> a = new List<int>(m);
        List<int> b = new List<int>(m);
        for (int i = 0; i < m; i++)
        {
            a.Add(cin.nextInt());
            b.Add(cin.nextInt());
        }

        int ans = 0;
        List<int> bridge = new List<int>();
        for(int i = 0; i < m; i++)
        {
            tempConnected = new bool[n];
            AddConnected(1, a, b, i);
            bool allconnected = true; for(int j = 0;j<n;j++) if (!tempConnected[j]) { allconnected = false;break; }
            if (!allconnected)
            {
                bridge.Add(i + 1);
                ans++;
            }
            //else
            //{
            //    showL($"{i + 1} is not bridge");
            //}
        }
        showL(ans);

        //sw.Stop();
        //showL($"処理時間: {sw.ElapsedMilliseconds} [msec]");


    }

    
    bool[] tempConnected;
    public void AddConnected(int index, List<int>a,List<int>b, int ignoreingBridge = -1)
    {
        //index番目のノードにつながるノードをconnectedにして、さらにaddconnectedを呼び出す
        for(int i = 0; i < a.Count; i++)
        {
            if (i == ignoreingBridge) continue;
            if (a[i] -1 == index && !tempConnected[b[i]-1]) { tempConnected[b[i]-1] = true; AddConnected(b[i]-1, a, b,ignoreingBridge); }
            else if (b[i]-1 == index && !tempConnected[a[i]-1]) { tempConnected[a[i]-1] = true; AddConnected(a[i]-1, a, b,ignoreingBridge); }
        }
   
    }
    public void backetSort(ref int[] a)
    {
        //max a << a.len に対して有効なソート
        //よってa = int[] とする
        long n = a.Length;
        var count = new int[n];
        var loc = new long[n];//loc[i] は i が終わる 位置 max index where c[index] = loc[i]
        for (long i = 0; i < n; i++) count[a[i]]++;
        loc[0] = count[0] - 1;
        for (long i = 0; i < n-1; i++) loc[i+1] = loc[i] + count[i+1]; 
        long index = 0;

        for(int i = 0; i < n; i++)
        {
            while (index <= loc[i]) a[index++] = i; //incex <= loc[i] == index < loc[i] + 1
        }
    }

    public static void showL<T>(T s) { Console.WriteLine(s); }
    public static void show<T>(T s) { Console.Write(s); }

}

class Printer : StreamWriter
{
    public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
    public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
    public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { }
}

class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        while (i >= s.Length)
        {
            string st = Console.ReadLine();
            while (st == "") st = Console.ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
        }
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }

    public int[] nextIntArr(long n)
    {
        int[] output = new int[n];
        for (int i = 0; i < n; i++) output[i] = nextInt();
        return output;
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }

}

class SMath
{
    
    /// <summary>
    /// 素因数分解して、n番目に見つかった素因数をoutput[n-1]に返します。
    /// 12 なら 2,2,3 です。
    /// </summary>
    /// <param name="n"></param>
    /// <returns></returns>
    public static List<long> Factorization(long n)
    {
        if (n <= 0) return null;
        List<long> output = new List<long>();
        int i = 2;
        long max = (long)Math.Sqrt(n); ;
        while (n > 1)
        {
            if (i > max) { output.Add(n); break; }
            while (n % i == 0)
            {
                output.Add(i);
                n /= i;
            }
            i++;
        }
        return output;
    }

    /// <summary>
    /// 素因数分解して、n番目に見つかった素因数をoutput[n-1]に返します。
    /// 84 = (2^2 * 3 * 7) なら 2, 1, 0, 1 　remainder = 1です。(打ち切られない）
    /// 13 = 0,0,...0 remainder = 2019
    /// ただし、試行を打ち切った時に限り残りをremainderに返す。(remainderは素数または1となる)
    /// </summary>
    /// <param name="n"></param>
    /// <param name="remainder"></param>
    /// <returns></returns>
    public static List<long> Factorization(long n, out long remainder)
    {
        //output[i] が i-1番目の素数の数を示す
        //ただし、試行を打ち切った時に限り残りをremainderに返す。(remainderは素数または1となる)
        remainder = 1;
        if (n <= 0) return null;
        List<long> output = new List<long>();
        long tempn = 2;
        long max = (long)Math.Sqrt(n);
        bool[] isNOTPrime = new bool[max+1];
        while (n > 1)
        {

            if (tempn > max) { remainder = n; break; }
            if (!isNOTPrime[tempn])
            {
                output.Add(0);
                while (n % tempn == 0)
                {
                    output[output.Count - 1]++;
                    n /= tempn;
                }
                for (long j = tempn * 2; j < isNOTPrime.Length; j += tempn) isNOTPrime[j] = true;
            }
            tempn++;
        }
        return output;
    }

    /// <summary>
    /// i番目の素数をoutput[i-1]に返します。
    /// ただしnより大きい素数については判定しません。
    /// </summary>
    /// <param name="n"></param>
    /// <returns></returns>
    public static List<long> GetPrimeNumbers(long n)
    {
        if (n <= 0) return null;
        List<long> output = new List<long>();
        long tempn = 2;
        bool[] isNOTPrime = new bool[n + 1];
        while (n > 1)
        {
            if (tempn > n) { break; }
            if (!isNOTPrime[tempn])
            {
                output.Add(tempn);
                for (long j = tempn * 2; j < isNOTPrime.Length; j += tempn) isNOTPrime[j] = true;
            }
            tempn++;
        }
        return output;
    }


    private static long[][] combMemo;
    private static int maxn_combination = -1;
    public static long Combination(int n, int k)
    {
        if (n < 0 || k > n) return 0;
        if (n == k || k == 0) return 1;
        if (k > n/2) return Combination(n, n - k);
        if (maxn_combination < n)
        {
            maxn_combination = n;
            combMemo = new long[n+1][];
        }
        if (combMemo[n] == null) combMemo[n] = new long[n/2 + 1];
        if (combMemo[n][k] != 0) return combMemo[n][k];
        else
        {
            combMemo[n][k] = Combination(n - 1, k) + Combination(n - 1, k - 1);
            return combMemo[n][k];
        }
        
    }
    public static long Gcd(long a, long b)
    {
        if (a <= 0) return -1;
        //if (a > b) return gcd(b, a);
        if (b == 0) return a;
        return Gcd(b, a % b);
    }
    public static long Lcm(long a,long b)
    {
        return a / Gcd(a, b) * b;
    }
}