#include <bits/stdc++.h>
using namespace std;
int main() {
  ios_base::sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  vector<int> graph[n];
  for (int i = 0; i < m; i++) {
    int x, y;
    cin >> x >> y;
    graph[x - 1].push_back(y - 1);
    graph[y - 1].push_back(x - 1);
  }
  if (!m) {
    cout << "3 " << ((long long)n * (n - 1) * (n - 2) / 6) << endl;
    return 0;
  }
  vector<int> distance(n, -1);
  queue<int> q;
  q.push(0);
  distance[0] = 0;
  bool found = false;
  while (!q.empty()) {
    int cur = q.front();
    q.pop();
    for (auto x : graph[cur]) {
      if (distance[x] == -1) {
        q.push(x);
        distance[x] = distance[cur] + 1;
      } else if (distance[x] == distance[cur])
        found = true;
    }
  }
  if (found) {
    cout << "0 1" << endl;
    return 0;
  }
  long long res = 0;
  for (int i = 0; i < n; i++) distance[i] = -1;
  for (int start = 0; start < n; start++) {
    if (distance[start] != -1) continue;
    distance[start] = 0;
    vector<long long> sizes(2, 0);
    q.push(start);
    while (!q.empty()) {
      int cur = q.front();
      q.pop();
      sizes[distance[cur] % 2]++;
      for (auto x : graph[cur]) {
        if (distance[x] == -1) {
          q.push(x);
          distance[x] = distance[cur] + 1;
        } else if (distance[x] == distance[cur])
          found = true;
      }
    }
    for (int i = 0; i < 2; i++) res += sizes[i] * (sizes[i] - 1) / 2;
  }
  if (res > 0) {
    cout << "1 " << (res) << endl;
    return 0;
  }
  cout << "2 " << ((long long)m * (n - 2)) << endl;
  return 0;
}
