Problem:
Score : 100 points

Problem Statement

Kyoto University Programming Contest is a programming contest voluntarily held by some Kyoto University students.
This contest is abbreviated as Kyoto University Programming Contest and called KUPC.

source: Kyoto University Programming Contest Information

The problem-preparing committee met to hold this year's KUPC and N problems were proposed there.
The problems are numbered from 1 to N and the name of i-th problem is P_i.
However, since they proposed too many problems, they decided to divide them into some sets for several contests.

They decided to divide this year's KUPC into several KUPCs by dividing problems under the following conditions.

One KUPC provides K problems.

Each problem appears at most once among all the KUPCs.

All the first letters of the problem names in one KUPC must be different.

You, one of the committee members, want to hold as many KUPCs as possible.
Write a program to find the maximum number of KUPCs that can be held this year.

Constraints

1 \leq N \leq 10^4

1 \leq K \leq 26

1 \leq |P_i| \leq 10

All characters in P_i are capital letters.

Note that, for each i and j (1 \leq i < j \leq N),
P_i \neq P_j are not necessarily satisfied.

Input

The input is given from Standard Input in the following format:

N K
P_1
:
P_N

Output

Print the maximum number of KUPCs that can be held on one line.

Sample Input 1

9 3
APPLE
ANT
ATCODER
BLOCK
BULL
BOSS
CAT
DOG
EGG

For example, three KUPCs can be held by dividing the problems as follows.

First: APPLE, BLOCK, CAT

Second: ANT, BULL, DOG

Third: ATCODER, BOSS, EGG

Sample Output 1

3

Sample Input 2

3 2
KU
KYOUDAI
KYOTOUNIV

Sample Output 2

0

No KUPC can be held.

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.IO;

#region Program
namespace Program
{
    #region Solver
    public class Solver
    {
        static IO.StreamScanner
        sc = new IO.StreamScanner(Console.OpenStandardInput());

        static readonly string AZ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        char[] AZAry;
        int[] AZCnt;

        int N;
        int K;
        string[] P;
        bool[] DONE;

        char[] POrder;

        #region Solver
        public Solver()
        {
            N = sc.Integer();
            K = sc.Integer();

            AZAry = new char[AZ.Length];
            AZAry = AZ.ToCharArray();

            P = new string[N];
            POrder = new char[N];
            DONE = new bool[N];
            AZCnt = new int[AZ.Length];
            for (int i = 0; i < N; i++)
            {
                P[i] = sc.Scan();
                AZCnt[AZ.IndexOf(P[i][0])]++;
                DONE[i] = false;
            }
            Array.Sort(AZCnt, AZAry);
        }
        #endregion

        #region Solve
        public void Solve()
        {
            int cnt = 0;
            int total = 0;
            char head = default(char);

            for (int j = 0; j < N; j++)
            {
                POrder[j] = P[j][0];
            }

            while (true)
            {
                if (N <= K * total) break;

                // 都度並び替える
                Array.Sort(AZCnt, AZAry);

                int order = 0;
                for (int i = AZ.Length - 1; 0 <= i; i--)
                {
                    char c = AZAry[i];
                    if (AZCnt[i] == 0) break;
                    for (int j = 0; j < N; j++)
                    {
                        if (POrder[j] == AZAry[i] && !DONE[j])
                        {
                            Swap(ref POrder[order], ref POrder[j]);
                            Swap(ref DONE[order], ref DONE[j]);
                            order++;
                        }
                    }
                }

                cnt = 0;
                head = head = default(char);

                for (int i = 0; i < N; i++)
                {
                    if (cnt >= K) break;

                    if (!DONE[i])
                    {
                        if (head != POrder[i])
                        {
                            head = POrder[i];
                            DONE[i] = true;
                            cnt++;

                            // アルファベットごとのカウント
                            AZCnt[Array.IndexOf(AZAry, POrder[i])]--;
                        }
                    }
                }
                if (cnt >= K) total++;
                else break;
            }
            Console.WriteLine(total);
        }
        #endregion

        #region Swap
        static void Swap<T>(ref T lhs, ref T rhs)
        {
            T temp;
            temp = lhs;
            lhs = rhs;
            rhs = temp;
        }
        #endregion
    }
    #endregion
}
#endregion

#region Execute
class Execute
{
    public static void Main(string[] args)
    {
        new Program.Solver().Solve();
        Program.IO.Printer.Out.Flush();
    }
}
#endregion

#region Program.IO
namespace Program.IO
{
    using System.Text;
    using System.Globalization;
    using System.Linq;
    public class Printer : StreamWriter
    {
        static Printer()
        {
            Out = new Printer(Console.OpenStandardOutput())
            {
                AutoFlush = false
            };
        }
        public static Printer Out
        {
            get;
            set;
        }
        public override IFormatProvider FormatProvider
        {
            get
            {
                return CultureInfo.InvariantCulture;
            }
        }
        public Printer(System.IO.Stream stream)
            : base(stream, new UTF8Encoding(false, true))
        {
        }
        public Printer(System.IO.Stream stream, Encoding encoding)
            : base(stream, encoding)
        {
        }
        public void Write<T>(string format, T[] source)
        {
            base.Write(format, source.OfType<object>().ToArray());
        }
        public void WriteLine<T>(string format, T[] source)
        {
            base.WriteLine(format, source.OfType<object>().ToArray());
        }
    }
    public class StreamScanner
    {
        public readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;
        public StreamScanner(Stream stream)
        {
            str = stream;
        }
        private T[] enumerate<T>(int n, Func<T> f)
        {
            var a = new T[n];
            for (int i = 0; i < n; ++i) a[i] = f();
            return a;
        }
        public long Long()
        {
            if (isEof)
            {
                return long.MinValue;
            }
            long ret = 0;
            byte b = 0;
            var ng = false;
            do
            {
                b = read();
            }
            while (b != '-' && (b < '0' || '9' < b));
            if (b == '-')
            {
                ng = true;
                b = read();
            }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                {
                    return ng ? -ret : ret;
                }
                else ret = ret * 10 + b - '0';
            }
        }
        public long[] Long(int n)
        {
            return enumerate(n, Long);
        }
        public int Integer()
        {
            return (isEof) ? int.MinValue : (int)Long();
        }
        public int[] Integer(int n)
        {
            return enumerate(n, Integer);
        }
        public char[] Char(int n)
        {
            return enumerate(n, Char);
        }
        public char Char()
        {
            byte b = 0;
            do
            {
                b = read();
            }
            while ((b < 33 || 126 < b) && !isEof);
            return (char)b;
        }
        public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
            {
                sb.Append(b);
            }
            return sb.ToString();
        }
        private byte read()
        {
            if (isEof)
            {
                return 0;
            }
            if (ptr >= len)
            {
                ptr = 0;
                if ((len = str.Read(buf, 0, 1024)) <= 0)
                {
                    isEof = true;
                    return 0;
                }
            }
            return buf[ptr++];
        }
    }
}
#endregion