#include <bits/stdc++.h>
using namespace std;
long long rdtsc() {
  long long tmp;
  asm("rdtsc" : "=A"(tmp));
  return tmp;
}
inline int myrand() { return abs((rand() << 15) ^ rand()); }
inline int rnd(int x) { return myrand() % x; }
struct Info {
  int mask;
  int value;
  Info() {}
  Info(int left, int right, int l) : value(0) {
    mask = 0;
    for (int i = 0; i < l; ++i)
      if ((right / (1 << i) - left / (1 << i)) & 1) mask ^= (1 << i);
  }
  Info(const Info &left, const Info &right) {
    value = min(left.value, right.value);
    mask = 0;
    if (left.value == value) mask ^= left.mask;
    if (right.value == value) mask ^= right.mask;
  }
};
struct NodeInfo {
  int toadd;
  Info info;
  NodeInfo() {}
  NodeInfo(int _toadd, const Info &_info) : toadd(_toadd), info(_info) {}
};
struct SegmTree {
  const static int maxn = (1 << 17);
  NodeInfo a[2 * maxn];
  int n;
  int wholeMask;
  void build(int cnt, int *xs, int l) {
    for (n = 1; n < cnt; n <<= 1)
      ;
    wholeMask = 0;
    for (int i = 0; i < n; ++i) {
      if (i < cnt - 1)
        a[i + n] = NodeInfo(0, Info(xs[i], xs[i + 1], l));
      else
        a[i + n] = NodeInfo(0, Info(0, 0, l));
      wholeMask ^= a[i + n].info.mask;
    }
    for (int i = n - 1; i; --i)
      a[i] = NodeInfo(0, Info(a[2 * i].info, a[2 * i + 1].info));
  }
  void push(int v) {
    if (a[v].toadd == 0) return;
    a[2 * v].toadd += a[v].toadd;
    a[2 * v].info.value += a[v].toadd;
    a[2 * v + 1].toadd += a[v].toadd;
    a[2 * v + 1].info.value += a[v].toadd;
    a[v].toadd = 0;
  }
  void update(int v) {
    a[v] = NodeInfo(0, Info(a[2 * v].info, a[2 * v + 1].info));
  }
  void add(int v, int l, int r, int l0, int r0, int toadd) {
    if (l >= r0 || l0 >= r) return;
    if (l0 <= l && r <= r0) {
      a[v].toadd += toadd;
      a[v].info.value += toadd;
      return;
    }
    push(v);
    int m = (l + r) / 2;
    add(2 * v, l, m, l0, r0, toadd);
    add(2 * v + 1, m, r, l0, r0, toadd);
    update(v);
  }
  void add(int l, int r, int toadd) { add(1, 0, n, l, r, toadd); }
  int getVal() const {
    assert(a[1].info.value == 0);
    return wholeMask ^ a[1].info.mask;
  }
} tree;
int l;
struct Event {
  int type, x, l, r;
  Event() {}
  Event(int _type, int _x, int _l, int _r) : type(_type), x(_x), l(_l), r(_r) {}
  inline bool operator<(const Event &e) const {
    if (x != e.x) return x < e.x;
    return 0;
  }
};
const int maxn = (int)1e5 + 10;
Event evs[maxn];
int xs[maxn];
bool solve() {
  int n, m, k;
  if (scanf("%d%d%d", &n, &m, &k) < 2) return 0;
  int res = 0;
  l = 0;
  for (; (1 << l) <= k; ++l)
    ;
  int cnt = 0;
  for (int i = 0; i < m; ++i) {
    int a, b, c, d;
    scanf("%d%d%d%d", &a, &b, &c, &d);
    --a, --b;
    evs[2 * i] = Event(0, a, b, d);
    evs[2 * i + 1] = Event(1, c, b, d);
    xs[cnt++] = b;
    xs[cnt++] = d;
  }
  sort(evs, evs + 2 * m);
  sort(xs, xs + cnt);
  cnt = unique(xs, xs + cnt) - xs;
  for (int i = 0; i < 2 * m; ++i) {
    evs[i].l = lower_bound(xs, xs + cnt, evs[i].l) - xs;
    evs[i].r = lower_bound(xs, xs + cnt, evs[i].r) - xs;
  }
  tree.build(cnt, xs, l);
  for (int i = 0; i < 2 * m; ++i) {
    Event &cur = evs[i];
    if (i > 0) {
      Info info(evs[i].x, evs[i - 1].x, l);
      int val = tree.getVal();
      for (int it = 0; it < l; ++it) {
        if (((info.mask >> it) & 1) && ((val >> it) & 1)) {
          res ^= (1 << it);
          res ^= (1 << it) / 2;
        }
      }
    }
    tree.add(cur.l, cur.r, !cur.type ? 1 : -1);
  }
  printf(res ? "Hamed\n" : "Malek\n");
  return 1;
}
int main() {
  srand(rdtsc());
  while (1) {
    if (!solve()) break;
  }
  return 0;
}
