#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
using i32 = int;
using i64 = long long;
using u8 = unsigned char;
using u32 = unsigned;
using u64 = unsigned long long;
using f64 = double;
using f80 = long double;
long long power(long long a, long long b, long long p) {
  if (!b) return 1;
  long long t = power(a, b / 2, p);
  t = t * t % p;
  if (b & 1) t = t * a % p;
  return t;
}
long long exgcd(long long a, long long b, long long &x, long long &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  long long px, py;
  long long d = exgcd(b, a % b, px, py);
  x = py;
  y = px - a / b * py;
  return d;
}
template <class T>
inline void freshmin(T &a, const T &b) {
  if (a > b) a = b;
}
template <class T>
inline void freshmax(T &a, const T &b) {
  if (a < b) a = b;
}
namespace io {
const int BUFSIZE = 1 << 20;
int isize, osize;
char ibuf[BUFSIZE + 10], obuf[BUFSIZE + 10];
char *is, *it, *os = obuf, *ot = obuf + BUFSIZE;
char getchar() {
  if (is == it) {
    is = ibuf;
    it = ibuf + fread(ibuf, 1, BUFSIZE, stdin);
    if (is == it) return EOF;
  }
  return *is++;
}
char getalpha() {
  char c = getchar();
  while (!isalpha(c)) c = getchar();
  return c;
}
void putchar(char c) {
  *os++ = c;
  if (os == ot) {
    fwrite(obuf, 1, BUFSIZE, stdout);
    os = obuf;
  }
}
int inp() {
  int x = 0, f = 0;
  char ch;
  for (ch = getchar(); !isdigit(ch); ch = getchar())
    if (ch == '-') f = 1;
  for (; isdigit(ch); x = x * 10 + ch - '0', ch = getchar())
    ;
  return f ? -x : x;
}
long long inp_ll() {
  long long x = 0;
  int f = 0;
  char ch;
  for (ch = getchar(); !isdigit(ch); ch = getchar())
    if (ch == '-') f = 1;
  for (; isdigit(ch); x = x * 10 + ch - '0', ch = getchar())
    ;
  return f ? -x : x;
}
template <class T>
bool read(T &x) {
  x = 0;
  char ch = getchar();
  if (ch == EOF) return 0;
  for (; !isdigit(ch);) {
    ch = getchar();
    if (ch == EOF) return 0;
  }
  for (; isdigit(ch); x = x * 10 + ch - '0', ch = getchar())
    ;
  return 1;
}
template <class T>
void write(T x) {
  static char s[22];
  static char *it = s + 20;
  static char *end = s + 20;
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  do {
    *--it = x % 10 + '0';
    x /= 10;
  } while (x);
  for (; it < end; ++it) putchar(*it);
}
template <>
void write(const char *s) {
  for (; *s; ++s) putchar(*s);
}
template <>
void write(char c) {
  putchar(c);
}
template <class T, class V>
void write(T x, V y) {
  write(x);
  write(y);
}
template <class T>
void writeln(T x) {
  write(x);
  putchar('\n');
}
struct ender {
  ~ender() {
    if (os != obuf) fwrite(obuf, 1, os - obuf, stdout);
  }
} __ender;
}  // namespace io
template <class T>
void print(const T &a) {
  for (auto x : a) printf("%d ", x);
  puts("");
}
const int MAXN = 1 << 18;
const int MAXK = 17;
const int INF = 1000000010;
using namespace io;
using tiii = tuple<int, int, int>;
int n, m;
vector<pair<int, int> > v[MAXN];
vector<tiii> e;
int pre[MAXN], weight[MAXN], dis[MAXN];
void dfs(int x) {
  for (auto p : v[x]) {
    int y = p.first, z = p.second;
    if (y == pre[x]) continue;
    pre[y] = x;
    weight[y] = z;
    dis[y] = dis[x] + 1;
    dfs(y);
  }
}
int F[MAXN];
int father(int x) { return F[x] == x ? x : F[x] = father(F[x]); }
const int K = 2;
const int mods[] = {1000000007, 998244353, 1000000009};
void FWT(int a[], int n, int mod) {
  int MOD = mod;
  for (int d = 1; d < n; d <<= 1)
    for (int m = d << 1, i = 0; i < n; i += m)
      for (int j = 0; j < d; j++) {
        long long x = a[i + j], y = a[i + j + d];
        a[i + j] = (x + y) % MOD;
        a[i + j + d] = (x - y + MOD) % MOD;
      }
}
void IFWT(int a[], int n, int mod) {
  int MOD = mod;
  int inv = (mod + 1) / 2;
  for (int d = 1; d < n; d <<= 1)
    for (int m = d << 1, i = 0; i < n; i += m)
      for (int j = 0; j < d; j++) {
        long long x = a[i + j], y = a[i + j + d];
        a[i + j] = (x + y) % MOD;
        a[i + j + d] = (x - y + MOD) % MOD;
        a[i + j] = (long long)a[i + j] * inv % MOD;
        a[i + j + d] = (long long)a[i + j + d] * inv % MOD;
      }
}
int a[K][MAXN];
int b[MAXN];
void solve() {
  n = inp();
  m = inp();
  int sum = 0;
  for (int i = 1; i <= n; ++i) F[i] = i;
  for (int i = 1; i <= m; ++i) {
    int x = inp(), y = inp(), z = inp();
    sum ^= z;
    int fx = father(x), fy = father(y);
    if (fx == fy) {
      e.push_back(tiii{x, y, z});
    } else {
      F[fx] = fy;
      v[x].push_back({y, z});
      v[y].push_back({x, z});
    }
  }
  dfs(1);
  for (int k = 0; k < K; ++k) {
    a[k][sum] = 1;
    FWT(a[k], 1 << 17, mods[k]);
  }
  for (auto p : e) {
    int x, y, z;
    tie(x, y, z) = p;
    vector<int> w(1, z);
    while (x != y) {
      if (dis[x] < dis[y]) swap(x, y);
      w.push_back(weight[x]);
      x = pre[x];
    }
    for (int k = 0; k < K; ++k) {
      for (int i = 0; i < 1 << 17; ++i) b[i] = 0;
      for (auto x : w) b[x]++;
      FWT(b, 1 << 17, mods[k]);
      for (int i = 0; i < 1 << 17; ++i) a[k][i] = (u64)a[k][i] * b[i] % mods[k];
    }
  }
  for (int k = 0; k < K; ++k) {
    IFWT(a[k], 1 << 17, mods[k]);
  }
  for (int i = 0; i < 1 << 17; ++i)
    if (a[0][i] || a[1][i]) {
      printf("%d %d\n", i, a[0][i]);
      break;
    }
}
int main() {
  solve();
  return 0;
}
