#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
string to_string(string s) { return '"' + s + '"'; }
string to_string(char s) { return string(1, s); }
string to_string(const char *s) { return to_string((string)s); }
string to_string(bool b) { return (b ? "true" : "false"); }
template <typename A>
string to_string(A);
template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template <typename A>
string to_string(A v) {
  bool f = 1;
  string r = "{";
  for (const auto &x : v) {
    if (!f) r += ", ";
    f = 0;
    r += to_string(x);
  }
  return r + "}";
}
void debug_out() { cout << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cout << " " << to_string(H);
  debug_out(T...);
}
inline int add(int a, int b) {
  a += b;
  if (a >= MOD) a -= MOD;
  return a;
}
inline int sub(int a, int b) {
  a -= b;
  if (a < 0) a += MOD;
  return a;
}
inline int mul(int a, int b) { return (int)((long long)a * b % MOD); }
inline int binpow(int a, int b) {
  int res = 1;
  while (b > 0) {
    if (b & 1) res = mul(res, a);
    a = mul(a, a);
    b /= 2;
  }
  return res;
}
inline int inv(int a) { return binpow(a, MOD - 2); }
int gcd(int a, int b, int &x, int &y) {
  if (a == 0) {
    x = 0, y = 1;
    return b;
  }
  int x1, y1;
  int d = gcd(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return d;
}
const int N = 1e5 + 5, M = 17;
int par[N], weight[N], level[N];
vector<pair<int, int> > g[N];
vector<pair<int, pair<int, int> > > cycles;
namespace BitTransform {
void Transform(vector<int> &a, bool invert) {
  int n = a.size();
  for (int len = 2; len <= n; len <<= 1) {
    int len2 = len / 2;
    for (int i = 0; i < n; i += len)
      for (int j = 0; j < len2; ++j) {
        int &u = a[i + j], &v = a[i + j + len2];
        tie(u, v) = make_pair(add(u, v), sub(u, v));
      }
  }
  int inv_n = inv(n);
  if (invert)
    for (int &x : a) x = 1ll * x * inv_n % MOD;
}
vector<int> conv(vector<int> a, vector<int> b) {
  Transform(a, false);
  Transform(b, false);
  for (int i = 0; i < a.size(); ++i) a[i] = 1ll * a[i] * b[i] % MOD;
  Transform(a, true);
  return a;
}
}  // namespace BitTransform
using namespace BitTransform;
void dfs(int v = 1, int prnt = 0, int prntW = 0, int d = 1) {
  par[v] = prnt, weight[v] = prntW, level[v] = d;
  for (auto p : g[v]) {
    int u = p.first, w = p.second;
    if (u == prnt) continue;
    if (level[u] && level[u] < level[v])
      cycles.push_back({w, {v, u}});
    else if (!level[u])
      dfs(u, v, w, d + 1);
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n, m, total = 0;
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int x, y, w;
    cin >> x >> y >> w;
    g[x].emplace_back(y, w);
    g[y].emplace_back(x, w);
    total ^= w;
  }
  dfs();
  if (cycles.empty()) {
    cout << total << " "
         << "0\n";
    return 0;
  }
  vector<int> can(1 << M), ways(1 << M);
  can[0] = ways[0] = 1;
  for (auto p : cycles) {
    vector<int> now(1 << M);
    int w = p.first, start = p.second.first, end = p.second.second;
    now[w] = 1;
    for (int i = start; i != end; i = par[i]) now[weight[i]]++;
    can = conv(can, now);
    ways = conv(ways, now);
    for (int i = 0; i < (1 << M); ++i) can[i] = (can[i] > 0);
  }
  int mn = -1;
  for (int i = 0; i < (1 << M); ++i)
    if (can[i] && (mn == -1 || (total ^ i) < (total ^ mn))) mn = i;
  cout << (total ^ mn) << " " << ways[mn] << "\n";
  return 0;
}
