#include <bits/stdc++.h>
const int N = 150005;
using namespace std;
int n, m;
struct Edge {
  int next, to, v;
} edge[N << 1];
int head[N], cnt = 1, dfn[N], low[N], DFN, co[N], C, vis[N], num[N], id[N];
int op[50][1 << 17], ops, op2[50][1 << 17], mod, inv;
stack<int> sta;
inline void add(int x, int y, int v) {
  edge[cnt].next = head[x], edge[cnt].to = y, edge[cnt].v = v, head[x] = cnt++;
}
inline void FWT_xor(int* s, int type) {
  for (int mid = 1; mid < (1 << 17); mid <<= 1) {
    for (int len = mid << 1, j = 0; j < (1 << 17); j += len) {
      for (int k = 0; k < (len >> 1); k++) {
        int v = s[j + k];
        s[j + k] = (s[j + k] + s[j + mid + k]) % mod,
              s[j + k + mid] = (v - s[j + mid + k]) % mod;
        if (type == -1) {
          s[j + k] = 1ll * s[j + k] * inv % mod;
          s[j + k + mid] = 1ll * s[j + k + mid] * inv % mod;
        }
      }
    }
  }
}
void tarjan(int x, int fa) {
  dfn[x] = low[x] = ++DFN, sta.push(x), vis[x] = 1;
  for (int i = head[x]; i; i = edge[i].next) {
    if (edge[i].to == fa) continue;
    if (vis[edge[i].to])
      low[x] = min(low[x], dfn[edge[i].to]);
    else if (!dfn[edge[i].to])
      tarjan(edge[i].to, x), low[x] = min(low[edge[i].to], low[x]);
  }
  if (dfn[x] == low[x]) {
    int t;
    ++C;
    do {
      t = sta.top(), vis[t] = 0, co[t] = C, ++num[C], sta.pop();
    } while (t != x);
  }
}
int main() {
  int ans = 1 << 28, tmp = 0, ansnum = 0;
  scanf("%d%d", &n, &m);
  for (int i = 1, a, b, c; i <= m; i++) {
    scanf("%d%d%d", &a, &b, &c);
    add(a, b, c), add(b, a, c);
    tmp ^= c;
  }
  tarjan(1, 0);
  for (int i = 1; i <= C; i++) {
    if (num[i] > 1) id[i] = ++ops;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = head[i]; j; j = edge[j].next) {
      if ((j & 1) && co[i] == co[edge[j].to]) {
        ++op[id[co[i]]][edge[j].v];
        ++op2[id[co[i]]][edge[j].v];
      }
    }
  }
  mod = 1e9 + 7, inv = 500000004;
  for (int i = 1; i <= ops; i++) FWT_xor(op[i], 1);
  for (int i = 1; i < ops; i++) {
    for (int j = 0; j < (1 << 17); j++)
      op[ops][j] = 1ll * op[ops][j] * op[i][j] % mod;
  }
  FWT_xor(op[ops], -1);
  mod = 998244353, inv = 499122177;
  for (int i = 1; i <= ops; i++) FWT_xor(op2[i], 1);
  for (int i = 1; i < ops; i++) {
    for (int j = 0; j < (1 << 17); j++)
      op2[ops][j] = 1ll * op2[ops][j] * op2[i][j] % mod;
  }
  FWT_xor(op2[ops], -1);
  for (int i = 0; i < (1 << 17); i++) {
    if (op[ops][i] || op2[ops][i]) {
      if ((i ^ tmp) < ans) ans = i ^ tmp, ansnum = op[ops][i];
    }
  }
  mod = 1e9 + 7;
  printf("%d %d", ans, (ansnum + mod) % mod);
  return 0;
}
