#include <bits/stdc++.h>
using namespace std;
enum Operation { AND, OR, XOR };
struct FastWalshHadamardTransform {
  int n;
  long long *a, *b, *c;
  FastWalshHadamardTransform(int p[], int ps, int q[], int qs, Operation op,
                             int offset = 0) {
    for (n = 1; n < max(ps, qs); n <<= 1)
      ;
    a = new long long[n];
    b = new long long[n];
    c = new long long[n];
    for (int i = 0; i < n; ++i) {
      a[i] = i <= ps ? p[i + offset] : 0;
      b[i] = i <= qs ? q[i + offset] : 0;
    }
  }
  FastWalshHadamardTransform(long long p[], int ps, long long q[], int qs,
                             Operation op, int offset = 0) {
    for (n = 1; n < max(ps, qs); n <<= 1)
      ;
    a = new long long[n];
    b = new long long[n];
    c = new long long[n];
    for (int i = 0; i < n; ++i) {
      a[i] = i <= ps ? p[i + offset] : 0;
      b[i] = i <= qs ? q[i + offset] : 0;
    }
  }
  FastWalshHadamardTransform(bool p[], int ps, bool q[], int qs, Operation op,
                             int offset = 0) {
    for (n = 1; n < max(ps, qs); n <<= 1)
      ;
    a = new long long[n];
    b = new long long[n];
    c = new long long[n];
    for (int i = 0; i < n; ++i) {
      a[i] = i <= ps ? p[i + offset] : 0;
      b[i] = i <= qs ? q[i + offset] : 0;
    }
  }
  ~FastWalshHadamardTransform() {
    delete[] a;
    delete[] b;
    delete[] c;
  }
  void dft(long long t[], Operation op, int inv = 1) {
    for (int i = 2; i <= n; i <<= 1) {
      for (int j = 0; j < n; j += i) {
        for (int k = 0; k < (i >> 1); ++k) {
          long long u = t[j + k];
          long long v = t[j + k + (i >> 1)];
          switch (op) {
            case AND:
              if (inv == 1) {
                t[j + k] = u + v;
                t[j + k + (i >> 1)] = v;
              } else {
                t[j + k] = u - v;
                t[j + k + (i >> 1)] = v;
              }
              break;
            case OR:
              if (inv == 1) {
                t[j + k] = u + v;
                t[j + k + (i >> 1)] = u;
              } else {
                t[j + k] = v;
                t[j + k + (i >> 1)] = u - v;
              }
              break;
            case XOR:
              t[j + k] = u + v;
              t[j + k + (i >> 1)] = u - v;
              if (inv == -1) {
                t[j + k] >>= 1;
                t[j + k + (i >> 1)] >>= 1;
              }
              break;
          }
        }
      }
    }
  }
  void fwht_aux(Operation op) {
    dft(a, op);
    dft(b, op);
    for (int i = 0; i < n; ++i) c[i] = a[i] * b[i];
    dft(c, op, -1);
  }
  void fwht(int *dest, Operation op, int destLen = 1000000000, int offset = 0) {
    fwht_aux(op);
    for (int i = 0; i < min(n, destLen); ++i) dest[i + offset] = c[i];
  }
  void fwht(long long *dest, Operation op, int destLen = 1000000000,
            int offset = 0) {
    fwht_aux(op);
    for (int i = 0; i < min(n, destLen); ++i) dest[i + offset] = c[i];
  }
  void fwht(bool *dest, Operation op, int destLen = 1000000000,
            int offset = 0) {
    fwht_aux(op);
    for (int i = 0; i < min(n, destLen); ++i) dest[i + offset] = c[i];
  }
};
vector<pair<int, int> > edges[100005];
int dfn[100005], low[100005], stp = 0;
int vst[100005];
pair<int, int> stk[100005];
int stks = 0;
long long freq[45][131072];
bool ok[45][131072];
int fs = 0;
void dfs(int u, int p) {
  dfn[u] = low[u] = ++stp;
  vst[u] = 2;
  for (auto v : edges[u]) {
    if (v.first == p || vst[v.first] == 1) continue;
    stk[++stks] = v;
    if (!dfn[v.first]) {
      dfs(v.first, u);
      low[u] = min(low[u], low[v.first]);
      if (low[v.first] >= dfn[u]) {
        int stks0 = stks;
        for (; stk[stks].first != v.first; --stks)
          ;
        if (stks0 - stks >= 1) {
          ++fs;
          for (int i = (stks0); i >= (stks); i--) {
            freq[fs][stk[i].second]++;
            ok[fs][stk[i].second] = 1;
          }
        }
        --stks;
      }
    } else {
      low[u] = min(low[u], dfn[v.first]);
    }
  }
  vst[u] = 1;
}
int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  int tot = 0;
  for (int i = (1); i <= (m); i++) {
    int u, v, w;
    scanf("%d %d %d", &u, &v, &w);
    edges[u].push_back({v, w});
    edges[v].push_back({u, w});
    tot ^= w;
  }
  memset(freq, 0, sizeof(freq));
  dfs(1, -1);
  if (!fs) {
    printf("%d 1\n", tot);
    return 0;
  }
  int mx = 131072;
  for (int i = (2); i <= (fs); i++) {
    FastWalshHadamardTransform fwht(freq[i - 1], mx, freq[i], mx, XOR);
    fwht.fwht(freq[i], XOR);
    for (int j = (0); j <= (mx - 1); j++) {
      freq[i][j] %= 1000000007;
    }
    FastWalshHadamardTransform fwhtBool(ok[i - 1], mx, ok[i], mx, XOR);
    fwhtBool.fwht(ok[i], XOR);
  }
  int mncost = 1000000000, count = 0;
  for (int j = (0); j <= (mx - 1); j++) {
    if (ok[fs][j] && (j ^ tot) < mncost) {
      mncost = j ^ tot;
      count = freq[fs][j];
    }
  }
  printf("%d %d\n", mncost, count);
  return 0;
}
