#include <stdio.h>
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <list>
#include <utility>
#include <set>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <bitset>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <random>

using namespace std;

static const double EPS = 1e-9;
template<class T> bool INRANGE(T x,T a,T b){return a<=x&&x<=b;}
template<class T> void amin(T &a,T v){if(a>v) a=v;}
template<class T> void amax(T &a,T v){if(a<v) a=v;}
int ROUND(double x) { return (int)(x+0.5); }
bool ISINT(double x) { return fabs(ROUND(x)-x)<=EPS; }
bool ISEQUAL(double x,double y) { return fabs(x-y)<=EPS*max(1.0,max(fabs(x),fabs(y))); }
double SQSUM(double x,double y) { return x*x+y*y; }
#define PI  (acos(-1))
#define ARRAY_NUM(a) (sizeof(a)/sizeof(a[0])) 
#define NG (-1)
#define BIG ((int)1e9+10)
#define BIGLL ((ll)4e18)
#define SZ(a) ((int)(a).size())
#define SQ(a) ((a)*(a))
typedef unsigned long long ull;
typedef long long ll;


#if 1

int countNumPairs(const vector <int>& x)
{
	int ret = 0;
	for (int i = 0; i < SZ(x)-1; ++i)
	{
		if (x[i] == x[i + 1])
		{
			ret++;
			i++;
		}
	}

	return ret;
}

int funcSame(const vector <int>& x)
{
	return SZ(x)/2;
}

int func(const vector <int>& x, const vector <int>& y)
{
	int nx = countNumPairs(x);
	int ny = countNumPairs(y);

	int ret = min(SZ(x),SZ(y));
	int diff = abs(SZ(x)-SZ(y));
	if (SZ(x) > SZ(y))
	{
		ret += min(diff/2, nx);
	}
	else
	{
		ret += min(diff / 2, ny);
	}

	return ret;
}


int main()
{
	int N, M;
	scanf("%d %d ",&N, &M);

	vector < vector <int> > md(M);
	for (int i = 0; i < N; ++i)
	{
		int x;
		scanf("%d ", &x);

		md[x%M].push_back(x);
	}

	for (int i = 0; i < M; ++i)
	{
		sort(md[i].begin(), md[i].end());
	}

	int ret = 0;
	for (int i = 0; i <= M/2; ++i)
	{
		int delta = 0;
		if (i == 0 || i * 2 == M)
		{
			delta = funcSame(md[i]);
		}
		else
		{
			delta = func(md[i], md[M-i]);
		}


		ret += delta;

		// BEGIN CUT HERE
//		cerr << " i=" << i << " delta=" << delta << " ret=" << ret << endl;
		// END CUT HERE

		
	}

	// BEGIN CUT HERE
	cout <<  ret << endl;
	// END CUT HERE


	return 0;
}


#elif 1

const int NUM = 10000;

int dp[101][NUM*2+100];

int main()
{
	ll N, A;
	cin >> N >> A;

	memset(dp,NG,sizeof(dp));


	int now = 0;

	dp[0][1] = 0;
	for (int t = 0; t<100; t++)
	{
		const int next = 1-now;

		for (int g=1;g<=NUM;g++)
		{
			if (dp[t][g]!=NG)
			{
				amax(dp[t+1][g], dp[t][g] + g);
				amax(dp[t+1][2 * g], 0);

				if (dp[t+1][g] >= A)
				{
					printf("%d\n",t+1);
					return 0;
				}
			}
		}

		now = next;
	}

	return 0;

/*
	cin >> N >> A;

	int q;

	ll g = 1;
	ll x = 0;
	ll t = 0;
	while (cin >> q)
	{
		// BEGIN CUT HERE
		cerr << " t=" << t << " g=" << g << " x=" << x << endl;
		// END CUT HERE

		if(x>=N) break;
		
		t++;
		x += g;
		if (q == 1)
		{
			g = x;
			x = 0;
			t++;
		}
	}


	return 0;
*/
}

#elif 1


// Union-Find法。無向グラフをつなげる。
void union_init(vector <int>& v, int size)
{
	v.clear();
	for (int i = 0; i < size; i++)
	{
		v.push_back(i);
	}
}

// union_connect後に、union_getすると、vはグループの代表番号が入る。v[n]=t行。
// 
int union_get(vector <int>& v, int n)
{
	int t = n;
	int k;
	while (v[t] != t)
	{
		t = v[t];
	}

	while (v[n] != n)
	{
		k = v[n];
		v[n] = t;
		n = k;
	}
	return n;
}


// ノードaとノードbをつなぐ。
// union_connect後のvには、同じグループに入るノードのうちの1つの番号が入る
bool union_connect(vector <int> & v, int a, int b)
{
	a = union_get(v, a);
	b = union_get(v, b);
	if (a == b)
	{
		return false;
	}

	v[a] = b;
	return true;
}



int main()
{
	int N,M;
	scanf("%d %d",&N, &M);

	vector < vector <int> > speakers(M);

	for (int i = 0; i < N; ++i)
	{
		int K;
		scanf("%d ", &K);

		for (int k = 0; k < K; ++k)
		{
			int l;
			scanf("%d ", &l);
			l--;

			speakers[l].push_back(i);
		}
	}

	vector <int> v;
	union_init(v, N);
	for(int l=0;l<M;++l)
	{
		for (int k = 0; k < SZ(speakers[l]) - 1; ++k)
		{
			union_connect(v, speakers[l][k], speakers[l][k+1]);
		}
	}

	vector <int> num_nodes(N); //
	for (int i = 0; i < N; i++)
	{
		num_nodes[union_get(v, i)]++;
	}

	bool ok = false;
	for(auto a : num_nodes)
	{
		if(a==N)
		{
			ok = true;
		}
	}

	if (ok)
	{
		cout << "YES" << endl;
	}
	else
	{
		cout << "NO" << endl;
	}

	return 0;
}


#elif 1

int main()
{
	ll N;
	cin >> N;

	for(ll hi=1;;hi++)
	{
		vector <ll> ans;
		ll sum = hi*(hi + 1) / 2;
		if (sum >= N)
		{
			for (ll dec = hi; dec >= 0; dec--)
			{
				if(N==0) break;

				if (N - dec >= 0)
				{
					ans.push_back(dec);
					N -= dec;
				}

			}

			reverse(ans.begin(),ans.end());
			for (ll a : ans)
			{
				cout << a << endl;
			}
			return 0;
		}
	}

	return 0;
}



#else

int main()
{
	int H,W;
	cin >> H >> W;

	for (int y = 0; y < H; ++y)
	{
		for (int x = 0; x < W; ++x)
		{
			string s;
			cin >> s;
			if (s == "snuke")
			{
				char a = 'A'+x;
				char b = 1+y;
				printf("%c%d\n",a,b);
				break;

			}

		}
	}



	return 0;
}

#endif

Measured memory_bytes: 5760