#include <bits/stdc++.h>
using namespace std;
class Edge {
 public:
  int to;
  long long cost;
  Edge(int t, long long c) : to(t), cost(c) {}
  Edge() {}
};
void get_prime(int N);
void add_edge(int u, int v, long long w);
const int MAX = 1e5 + 5, MAXP = 2e5 + 5;
const long long INF = 1e9;
vector<Edge> graph[MAX];
vector<long long> primes;
bool visited[MAXP];
int main() {
  get_prime(MAXP - 5 + 1);
  int n, m;
  while (scanf("%d %d", &n, &m) != EOF) {
    for (int i = 0; i < MAX; i++) {
      graph[i].clear();
    }
    for (int i = 1; i <= n - 2; i++) {
      add_edge(i, i + 1, 1);
      m--;
    }
    vector<long long>::iterator it =
        lower_bound(primes.begin(), primes.end(), n - 1);
    add_edge(n - 1, n, *it - (n - 2));
    m--;
    for (int i = 1; i + 2 <= n && m > 0; i++) {
      for (int j = i + 2; j <= n && m > 0; j++) {
        add_edge(i, j, INF);
        m--;
      }
    }
    printf("%lld %lld\n", *it, *it);
    for (int i = 1; i <= n; i++)
      for (auto e : graph[i]) {
        if (i < e.to) printf("%d %d %lld\n", i, e.to, e.cost);
      }
  }
  return 0;
}
void get_prime(int N) {
  for (int i = 2; i <= N; i++) {
    if (!visited[i]) {
      primes.push_back(i);
    }
    for (int j = 0; j < primes.size() && i * primes[j] <= N; j++) {
      visited[i * primes[j]] = true;
      if (i % primes[j] == 0) {
        break;
      }
    }
  }
}
inline void add_edge(int u, int v, long long w) {
  graph[u].push_back(Edge(v, w));
  graph[v].push_back(Edge(u, w));
}
