#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int maxv = 1 << 17;
const double eps = 1e-7;
struct FWT {
  const static int mod = 1e9 + 7, inv2 = 5e8 + 4;
  int sz = 0;
  int add(int x, int y) { return ((x + y) % mod + mod) % mod; }
  int mul(int x, int y) { return (1LL * x * y) % mod; }
  void FWTxor(int *p, int inv) {
    for (int len = 1; 2 * len <= sz; len <<= 1) {
      for (int i = 0; i < sz; i += 2 * len) {
        for (int j = 0; j < len; j++) {
          int x = p[i + j], y = p[i + j + len];
          p[i + j] = add(x, y);
          p[i + j + len] = add(x, -y);
          if (inv) {
            p[i + j] = mul(p[i + j], inv2);
            p[i + j + len] = mul(p[i + j + len], inv2);
          }
        }
      }
    }
  }
  void FWTxor(double *p, int inv) {
    for (int len = 1; 2 * len <= sz; len <<= 1) {
      for (int i = 0; i < sz; i += 2 * len) {
        for (int j = 0; j < len; j++) {
          double x = p[i + j], y = p[i + j + len];
          p[i + j] = x + y;
          p[i + j + len] = x - y;
          if (inv) {
            p[i + j] = p[i + j] / 2;
            p[i + j + len] = p[i + j + len] / 2;
          }
        }
      }
    }
  }
} fwt;
int n, m;
vector<int> way[maxn];
map<int, map<int, int>> edge;
int cur, low[maxn], num[maxn];
stack<int> st;
int id, vec[45][maxv + 5];
int ans[maxv + 5];
double vec2[45][maxv + 5];
double ans2[maxv + 5];
void tarjan(int u, int last) {
  low[u] = num[u] = ++cur;
  st.push(u);
  for (auto v : way[u]) {
    if (v == last) continue;
    if (!num[v]) {
      tarjan(v, u);
      low[u] = min(low[u], low[v]);
    } else
      low[u] = min(low[u], num[v]);
  }
  if (num[u] == low[u]) {
    vector<int> have;
    while (!st.empty()) {
      int x = st.top();
      st.pop();
      have.push_back(x);
      if (x == u) break;
    }
    if (have.size() > 1) {
      id++;
      have.push_back(have[0]);
      int sz = have.size();
      for (int i = 1; i < sz; i++) {
        vec[id][edge[have[i]][have[i - 1]]]++;
        vec2[id][edge[have[i]][have[i - 1]]] = 1;
      }
    }
  }
}
int main() {
  scanf("%d%d", &n, &m);
  int sum = 0;
  for (int i = 1; i <= m; i++) {
    int u, v, val;
    scanf("%d%d%d", &u, &v, &val);
    way[u].push_back(v);
    way[v].push_back(u);
    edge[u][v] = edge[v][u] = val;
    sum = sum ^ val;
  }
  for (int u = 1; u <= n; u++)
    if (!num[u]) tarjan(u, 0);
  fwt.sz = maxv;
  ans[sum] = 1;
  fwt.FWTxor(ans, 0);
  ans2[sum] = 1;
  fwt.FWTxor(ans2, 0);
  for (int x = 1; x <= id; x++) {
    fwt.FWTxor(vec[x], 0);
    fwt.FWTxor(vec2[x], 0);
    for (int i = 0; i < maxv; i++) {
      ans[i] = fwt.mul(ans[i], vec[x][i]);
      ans2[i] = ans2[i] * vec2[x][i];
    }
  }
  fwt.FWTxor(ans, 1);
  fwt.FWTxor(ans2, 1);
  for (int i = 0; i < maxv; i++) {
    if (ans2[i] >= eps) {
      printf("%d %d\n", i, ans[i]);
      return 0;
    }
  }
}
