#include <bits/stdc++.h>
using namespace std;
const int mod1 = (int)1e9 + 7;
const int mod2 = 998244353;
pair<int, int> sum(pair<int, int> a, pair<int, int> b) {
  pair<int, int> res;
  res.first = a.first + b.first;
  if (res.first >= mod1) res.first -= mod1;
  res.second = a.second + b.second;
  if (res.second >= mod2) res.second -= mod2;
  return res;
}
pair<int, int> sub(pair<int, int> a, pair<int, int> b) {
  pair<int, int> res;
  res.first = a.first - b.first;
  if (res.first < 0) res.first += mod1;
  res.second = a.second - b.second;
  if (res.second < 0) res.second += mod2;
  return res;
}
pair<int, int> mult(pair<int, int> a, pair<int, int> b) {
  return {(a.first * 1LL * b.first) % mod1, (a.second * 1LL * b.second) % mod2};
}
int bin_pow(int a, int n, int mod) {
  int res = 1;
  for (; n; n >>= 1, a = (a * 1LL * a) % mod)
    if (n & 1) res = (res * 1LL * a) % mod;
  return res;
}
pair<int, int> inv(pair<int, int> a) {
  return {bin_pow(a.first, mod1 - 2, mod1), bin_pow(a.second, mod2 - 2, mod2)};
}
const int L = 17;
const int N = 1 << L;
int bit(int mask, int i) { return (mask >> i) & 1; }
int rev(int mask, int n = L) { return (~mask) & ((1 << n) - 1); }
void mask_print(int mask, int n = L) {
  for (int i = 0; i < n; ++i) printf("%d", bit(mask, i));
}
void fwht_xor(pair<int, int>* a, bool inverse) {
  pair<int, int> x, y;
  for (int l = 0; l < L; ++l) {
    for (int i = 0; i < N; ++i) {
      if (bit(i, l)) {
        x = a[i - (1 << l)];
        y = a[i];
        a[i - (1 << l)] = sum(x, y);
        a[i] = sub(x, y);
      }
    }
  }
  if (inverse) {
    pair<int, int> invN = inv({N, N});
    for (int i = 0; i < N; ++i) a[i] = mult(a[i], invN);
  }
}
const int maxn = (int)1e5 + 5;
vector<pair<int, int> > g[maxn];
int tin[maxn], tout[maxn], tup[maxn];
bool used[maxn];
void dfs(int v, int p) {
  static int TIME = 0;
  tin[v] = TIME++;
  tup[v] = tin[v];
  used[v] = true;
  for (auto& [u, w] : g[v]) {
    if (u == p) continue;
    if (!used[u]) {
      dfs(u, v);
      tup[v] = min(tup[v], tup[u]);
    } else {
      tup[v] = min(tup[v], tin[u]);
    }
  }
}
bool check(int v, int u) {
  if (tin[v] > tin[u]) swap(u, v);
  return tup[u] > tin[v];
}
int cnt[N];
pair<int, int> a[N], p[N];
int tour(int v, int p) {
  used[v] = true;
  int res = 1;
  for (auto& [u, w] : g[v]) {
    if (!check(u, v)) {
      cnt[w] += (int)(u < v);
      if (!used[u]) res += tour(u, v);
    }
  }
  return res;
}
int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  int total = 0;
  while (m--) {
    int u, v, w;
    scanf("%d %d %d", &u, &v, &w);
    --u;
    --v;
    total ^= w;
    g[u].push_back({v, w});
    g[v].push_back({u, w});
  }
  memset(used, false, sizeof(used));
  dfs(0, -1);
  memset(used, false, sizeof(used));
  for (int i = 0; i < N; ++i) p[i] = {1, 1};
  for (int v = 0; v < n; ++v) {
    if (used[v]) continue;
    memset(cnt, 0, sizeof(cnt));
    if (tour(v, -1) == 1) continue;
    for (int i = 0; i < N; ++i) a[i] = {cnt[i], cnt[i]};
    fwht_xor(a, false);
    for (int i = 0; i < N; ++i) p[i] = mult(p[i], a[i]);
  }
  fwht_xor(p, true);
  int ans = (1 << 18) - 1, ways = 1;
  for (int i = 0; i < N; ++i) {
    if ((p[i].first | p[i].second) && ans > (total ^ i)) {
      ans = total ^ i;
      ways = p[i].first;
    }
  }
  printf("%d %d\n", ans, ways);
}
