import std.stdio;
import std.array;
import std.string;
import std.conv;
import std.algorithm;
import std.typecons;
import std.range;
import std.random;
import std.math;
import std.container;
import std.numeric;
import std.bigint;


class FordFulkerson {
  int N, source, sink;
  int[][] adj;
  int[][] flow;
  bool[] used;

  this(int n, int s, int t) {
    N = n;
    source = s;
    sink = t;
    assert (s >= 0 && s < N && t >= 0 && t < N);
    adj = new int[][](N);
    flow = new int[][](N, N);
    used = new bool[](N);
  }

  void add_edge(int from, int to, int cap) {
    adj[from] ~= to;
    adj[to] ~= from;
    flow[from][to] = cap;
  }

  int dfs(int v, int min_cap) {
    if (v == sink)
      return min_cap;
    if (used[v])
      return 0;
    used[v] = true;
    foreach (to; adj[v]) {
      if (!used[to] && flow[v][to] > 0) {
        auto bottleneck = dfs(to, min(min_cap, flow[v][to]));
        if (bottleneck == 0) continue;
        flow[v][to] -= bottleneck;
        flow[to][v] += bottleneck;
        return bottleneck;
      }
    }
    return 0;
  }

  int run() {
    int ret = 0;
    while (true) {
      foreach (i; 0..N) used[i] = false;
      int f = dfs(source, int.max);
      if (f > 0)
        ret += f;
      else
        return ret;
    }
  }
}

void main() {
  auto input = readln.split.map!(to!int);
  auto N = input[0];
  auto M = input[1];
  auto X = readln.split.map!(to!int).array;
  auto cnt = new int[][](M);
  foreach (x; X) cnt[x%M] ~= x;
  auto amari = new int[](10^^5+1);

  int ans = 0;
  foreach (m; 0..M/2+1) {
    int minm, mm;
    if (m == 0 || (m == M/2 && M % 2 == 0)) {
      ans += cnt[m].length/2;
    }
    else {
      minm = min(cnt[m].length, cnt[M-m].length).to!int;
      mm = cnt[m].length > cnt[M-m].length ? m : M-m;
      int[int] same;
      foreach (x; cnt[mm]) {
        if (x in same) same[x] += 1;
        else same[x] = 1;
      }
      ans += minm + min(cnt[mm].length-minm, same.values.map!(x => x/2).sum);
    }
  }

  writeln(ans);
}
