#include <bits/stdc++.h>
using namespace std;
int N, M;
vector<int> adj[100000];
int color[100000];
int cpnt = 0;
int red[100000];
int blue[100000];
bool dfs_bipartite(int node, int c) {
  if (color[node] == c) {
    return true;
  }
  if (color[node] != 0 && color[node] != c) {
    return false;
  }
  color[node] = c;
  if (c == 1) {
    red[cpnt]++;
  } else {
    blue[cpnt]++;
  }
  int new_color = 3 - c;
  for (int next : adj[node]) {
    bool result = dfs_bipartite(next, new_color);
    if (!result) {
      return false;
    }
  }
  return true;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> N >> M;
  for (int i = 0; i < M; i++) {
    int A, B;
    cin >> A >> B;
    A--;
    B--;
    adj[A].push_back(B);
    adj[B].push_back(A);
  }
  if (M == 0) {
    long long ans = ((long long)N) * (N - 1) * (N - 2) / 6;
    cout << 3 << ' ' << ans << endl;
    return 0;
  }
  for (int i = 0; i < N; i++) {
    if (color[i] == 0) {
      bool result = dfs_bipartite(i, 1);
      if (!result) {
        cout << 0 << ' ' << 1 << endl;
        return 0;
      }
      cpnt++;
    }
  }
  bool bad = true;
  long long ans = 0;
  for (int cp = 0; cp < cpnt; cp++) {
    if (red[cp] + blue[cp] > 2) {
      bad = false;
    }
    ans += (((long long)red[cp]) * (red[cp] - 1)) / 2;
    ans += (((long long)blue[cp]) * (blue[cp] - 1)) / 2;
  }
  if (!bad) {
    cout << 1 << ' ' << ans << endl;
  } else {
    cout << 2 << ' ' << ((long long)M) * (N - 2) << endl;
  }
  return 0;
}
