Problem:
Score : 700 points

Problem Statement

Takahashi is playing with N cards.

The i-th card has an integer X_i on it.

Takahashi is trying to create as many pairs of cards as possible satisfying one of the following conditions:

The integers on the two cards are the same.

The sum of the integers on the two cards is a multiple of M.

Find the maximum number of pairs that can be created.

Note that a card cannot be used in more than one pair.

Constraints

2≦N≦10^5

1≦M≦10^5

1≦X_i≦10^5

Input

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

N M
X_1 X_2 ... X_N

Output

Print the maximum number of pairs that can be created.

Sample Input 1

7 5
3 1 4 1 5 9 2

Sample Output 1

3

Three pairs (3,2), (1,4) and (1,9) can be created.

It is possible to create pairs (3,2) and (1,1), but the number of pairs is not maximized with this.

Sample Input 2

15 10
1 5 6 10 11 11 11 20 21 25 25 26 99 99 99

Sample Output 2

6

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

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




namespace contest
{

    class contest
    {


        static void Main(string[] args)
        {


            var num = Console.ReadLine().Split().Select(int.Parse).ToArray();
            var card = Console.ReadLine().Split().Select(int.Parse).ToArray();
            int n = num[0];
            int m = num[1];
            Array.Sort(card);

            var dic = new SortedDictionary<int, List<int>>();

            for(int i=0; i< n; i++)
            {
                int tmp = card[i] % m;
                if (!dic.Keys.Contains(tmp))
                {
                    dic[tmp] = new List<int>();
                    
                }
                dic[tmp].Add(card[i]);

            }

            int count = 0;
            var memo = new bool[m+1];

            foreach(var item in dic)
            {
                int tmp = item.Key;
                var setA = item.Value;
                if (memo[tmp]) continue;

                if (tmp == 0 || ( m%2==0 &&  tmp == m / 2))
                {
                    count += setA.Count() / 2;
                    memo[tmp] = true;

                }
                else
                {
                    int res = m - tmp;
                    if (memo[res]) continue;

                    if (dic.Keys.Contains(res))
                    {
                        var setB = dic[res];

                        count += calc(setA, setB);

                        memo[tmp] = true;
                        memo[res] = true;

                    }
					else
                    {
                        setA.Sort();
                        for(int j=0; j<setA.Count()-1; j++)
                        {
                            if(setA[j]== setA[j+1])
                            {
                                count++;
                                j++;
                            }
                        }
                        memo[tmp] = true;
                    }
                }

            }


            Console.WriteLine(count);
			

        }

        public static int calc(List<int> a, List<int> b)
        {
            int count = 0;
            if(a.Count()<b.Count())
            {
                var tmp = new List<int>(a);
                a = new List<int>(b) ;
                b = new List<int>(tmp);
            }
            a.Sort();
            //b.Sort();

            int res = a.Count() - b.Count();
            res /= 2;
            

            int cnt = 0;
            for(int i =0; i<a.Count()-1 && cnt<res; i++)
            {
                if(a[i] == a[i+1])
                {
                    cnt++;                
                    i++;
                }

            }
            count = b.Count() + cnt;

            return count;
        }

    }


    
    
}