#pragma GCC optimize("Ofast")
#pragma GCC target("avx2")

#include <array>
#include <bitset>
#include <cmath>
#include <iostream>
#include <map>

static inline void set_flag(unsigned long *flags, const int POSITION) {
  *flags |= (1 << POSITION);
}

static inline int read_flag(unsigned long* flags, const int POSITION) {
  return (*flags & (1 << POSITION)) != 0;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int N, K;
  std::cin >> N >> K;

  std::map<std::array<int, 3>, int> testcases;

  for (int i = 0; i < K; ++i) {
    int one, two, three;
    std::cin >> one >> two >> three;
    ++testcases[{one, two, three}];
  }

  int max = 0;
  int boards_have_max = 0;
  int instances = pow(2, N);

  for (unsigned long i = 0; i < instances; ++i) {
    int current = 0;
/*    for (int j = 0; j < K; ++j) {
      if (read_flag(&i, testcases[j][0] - 1) == 1 && read_flag(&i, testcases[j][1] - 1) == 0 && read_flag(&i, testcases[j][2] - 1) == 0)
        ++current;
    }*/

    for (const auto& [array, freq] : testcases) {
      if (read_flag(&i, array[0] - 1) == 1 && read_flag(&i, array[1] - 1) == 0 && read_flag(&i, array[2] - 1) == 0)
        current += freq;
    }

    if (current > max) {
      max = current;
      boards_have_max = 1;
    } else if (current == max) {
      ++boards_have_max;
    }
  }
  std::cout << max << ' ' << boards_have_max;
}
