#include <bits/stdc++.h>

#define itn int
#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())

#define random_shuffle(...) shuffle(__VA_ARGS__, rng)
#define rand() rng()

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int L = 17;
const int N = 1 << L;

long long a[N];
long long b[N];

void wh(long long* b, long long* e) {
	if (e == b + 1) {
		return;
	}
	long long *m = b + (e - b) / 2;
	wh(b, m);
	wh(m, e);
	while (m != e) {
		*b += *m;
		*m = *b - 2 * (*m);
		++b, ++m;
	}
}

vector<pair<int, int>> g[N];
vector<int> huili;
vector<char> used;
vector<pair<int, int>> order;

void dfs(int v, int p) {
	used[v] = 1;
	for (const auto& [to, id] : g[v]) {
		if (id == p) {
			continue;
		}
		if (used[to] == 1) {
			continue;
		} else if (used[to]) {
			huili.push_back(id);
		} else {
			dfs(to, id);
		}
	}
	if (p > -1) {
		order.push_back({v, p});
	}
	used[v] = 2;
}

int main() {
	int n = nxt(), m = nxt();
	vector<int> w(m);
	for (int i = 0; i < m; ++i) {
		itn u = nxt() - 1, v = nxt() - 1;
		w[i] = nxt();
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}

	used.assign(n, 0);

	dfs(0, -1);
	vector<long long> shit(m);
	for (int x : huili) {
		shit[x] = rand() % 1000000000;
		shit[x] <<= 31;
		shit[x] |= (long long)rand() % 1000000000;
	}
	for (const auto& [v, id] : order) {
		for (const auto& [to, idx] : g[v]) {
			assert(to > -1);
			if (id == idx) {
				continue;
			}
			shit[id] ^= shit[idx];
		}
	}

	vector<char> bridges(m);
	int off = 0;
	for (int i = 0; i < m; ++i) {
		bridges[i] = (shit[i] == 0);
		off ^= w[i];
	}

	used.assign(n, 0);
	a[off] = 1;

	const int mod = 1000000007;
	int d2 = 1;
	for (int i = 0; i < L; ++i) {
		if (d2 % 2) {
			d2 += mod;
		}
		d2 /= 2;
	}
	for (int i = 0; i < n; ++i) {
		if (used[i]) {
			continue;
		}
		vector<int> st = {i};
		used[i] = 1;
		int cn = 0;
		while (!st.empty()) {
			++cn;
			int v = st.back();
			st.pop_back();
			for (const auto& [to, id] : g[v]) {
				if (bridges[id]) {
					continue;
				}
				b[w[id]] += 1;
				if (!used[to]) {
					used[to] = 1;
					st.push_back(to);
				}
			}
		}
		if (cn == 1) {
			continue;
		}
		for (int i = 0; i < N; ++i) {
			b[i] /= 2;
		}
		wh(a, a + N);
		wh(b, b + N);
		for (int i = 0; i < N; ++i) {
			a[i] %= mod;
			b[i] %= mod;
			if (a[i] < 0) {
				a[i] += mod;
			}
			if (b[i] < 0) {
				b[i] += mod;
			}
			a[i] *= b[i];
			a[i] %= mod;
		}
		wh(a, a + N);
		for (int i = 0; i < N; ++i) {
			a[i] = a[i] % mod * d2 % mod;
			if (a[i] < 0) {
				a[i] += mod;
			}
		}
		memset(b, 0, sizeof(b));
	}

	int idx = 0;
	while (a[idx] == 0) {
		++idx;
	}
	cout << idx << " " << a[idx] << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define itn int
#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())

#define random_shuffle(...) shuffle(__VA_ARGS__, rng)
#define rand() rng()

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int L = 3;
const int N = 1 << L;

long long a[N];
long long b[N];

void wh(long long* b, long long* e) {
	if (e == b + 1) {
		return;
	}
	long long *m = b + (e - b) / 2;
	wh(b, m);
	wh(m, e);
	while (m != e) {
		*b += *m;
		*m = *b - 2 * (*m);
		++b, ++m;
	}
}

int main() {
	int n = nxt(), m = nxt();
	vector<vector<pair<int, int>>> g(n);
	vector<int> w(m);
	for (int i = 0; i < m; ++i) {
		itn u = nxt() - 1, v = nxt() - 1;
		w[i] = nxt();
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}

	vector<int> huili;
	vector<char> used(n);
	vector<pair<int, int>> order;
	function<void(int, int)> dfs = [&](int v, int p) {
		used[v] = 1;
		for (const auto& [to, id] : g[v]) {
			if (id == p) {
				continue;
			}
			if (used[to] == 1) {
				continue;
			} else if (used[to]) {
				huili.push_back(id);
			} else {
				dfs(to, id);
			}
		}
		if (p > -1) {
			order.push_back({v, p});
		}
		used[v] = 2;
	};

	dfs(0, -1);
	vector<long long> shit(m);
	for (int x : huili) {
		shit[x] = rand() % 1000000000;
		shit[x] <<= 32;
		shit[x] |= rand();
	}
	for (const auto& [v, id] : order) {
		for (const auto& [to, idx] : g[v]) {
			assert(to > -1);
			if (id == idx) {
				continue;
			}
			shit[id] ^= shit[idx];
		}
	}

	vector<char> bridges(m);
	int off = 0;
	for (int i = 0; i < m; ++i) {
		bridges[i] = (shit[i] == 0);
		off ^= w[i];
	}

	used.assign(n, 0);
	a[off] = 1;

	const int mod = 1000000007;
	int d2 = 1;
	for (int i = 0; i < L; ++i) {
		if (d2 % 2) {
			d2 += mod;
		}
		d2 /= 2;
	}
	for (int i = 0; i < n; ++i) {
		if (used[i]) {
			continue;
		}
		memset(b, 0, sizeof(b));
		vector<int> st = {i};
		used[i] = 1;
		while (!st.empty()) {
			int v = st.back();
			st.pop_back();
			for (const auto& [to, id] : g[v]) {
				if (bridges[id]) {
					continue;
				}
				b[w[id]] += 1;
				if (!used[to]) {
					used[to] = 1;
					st.push_back(to);
				}
			}
		}
		b[0] += 2;
		for (int i = 0; i < N; ++i) {
			b[i] /= 2;
		}
		wh(a, a + N);
		wh(b, b + N);
		for (int i = 0; i < N; ++i) {
			a[i] *= b[i];
			a[i] %= mod;
		}
		wh(a, a + N);
		for (int i = 0; i < N; ++i) {
			a[i] = a[i] % mod * d2 % mod;
		}
	}

	int idx = 0;
	while (a[idx] == 0) {
		++idx;
	}
	cout << idx << " " << a[idx] << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define itn int
#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())

#define random_shuffle(...) shuffle(__VA_ARGS__, rng)
#define rand() rng()

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int L = 17;
const int N = 1 << L;

long long a[N];
long long b[N];

void wh(long long* b, long long* e) {
	if (e == b + 1) {
		return;
	}
	long long *m = b + (e - b) / 2;
	wh(b, m);
	wh(m, e);
	while (m != e) {
		*b += *m;
		*m = *b - 2 * (*m);
		++b, ++m;
	}
}

vector<pair<int, int>> g[N];
vector<int> huili;
vector<char> used;
vector<pair<int, int>> order;

void dfs(int v, int p) {
	used[v] = 1;
	for (const auto& [to, id] : g[v]) {
		if (id == p) {
			continue;
		}
		if (used[to] == 1) {
			continue;
		} else if (used[to]) {
			huili.push_back(id);
		} else {
			dfs(to, id);
		}
	}
	if (p > -1) {
		order.push_back({v, p});
	}
	used[v] = 2;
}

int main() {
	int n = nxt(), m = nxt();
	vector<int> w(m);
	for (int i = 0; i < m; ++i) {
		itn u = nxt() - 1, v = nxt() - 1;
		w[i] = nxt();
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}

	used.assign(n, 0);

	dfs(0, -1);
	vector<long long> shit(m);
	for (int x : huili) {
		shit[x] = rand() % 1000000000;
		shit[x] <<= 31;
		shit[x] |= (long long)rand() % 1000000000;
	}
	for (const auto& [v, id] : order) {
		for (const auto& [to, idx] : g[v]) {
			assert(to > -1);
			if (id == idx) {
				continue;
			}
			shit[id] ^= shit[idx];
		}
	}

	vector<char> bridges(m);
	int off = 0;
	for (int i = 0; i < m; ++i) {
		bridges[i] = (shit[i] == 0);
		off ^= w[i];
	}

	used.assign(n, 0);
	a[off] = 1;

	const int mod = 1000000007;
	int d2 = 1;
	for (int i = 0; i < L; ++i) {
		if (d2 % 2) {
			d2 += mod;
		}
		d2 /= 2;
	}
	for (int i = 0; i < n; ++i) {
		if (used[i]) {
			continue;
		}
		memset(b, 0, sizeof(b));
		vector<int> st = {i};
		used[i] = 1;
		int cn = 0;
		while (!st.empty()) {
			++cn;
			int v = st.back();
			st.pop_back();
			for (const auto& [to, id] : g[v]) {
				if (bridges[id]) {
					continue;
				}
				b[w[id]] += 1;
				if (!used[to]) {
					used[to] = 1;
					st.push_back(to);
				}
			}
		}
		if (cn == 1) {
			continue;
		}
		for (int i = 0; i < N; ++i) {
			b[i] /= 2;
		}
		wh(a, a + N);
		wh(b, b + N);
		for (int i = 0; i < N; ++i) {
			a[i] *= b[i];
			a[i] %= mod;
		}
		wh(a, a + N);
		for (int i = 0; i < N; ++i) {
			a[i] = a[i] % mod * d2 % mod;
		}
	}

	int idx = 0;
	while (a[idx] == 0) {
		++idx;
	}
	cout << idx << " " << a[idx] << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define itn int
#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())

#define random_shuffle(...) shuffle(__VA_ARGS__, rng)
#define rand() rng()

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int L = 17;
const int N = 1 << L;

long long a[N];
long long b[N];

void wh(long long* b, long long* e) {
	if (e == b + 1) {
		return;
	}
	long long *m = b + (e - b) / 2;
	wh(b, m);
	wh(m, e);
	while (m != e) {
		*b += *m;
		*m = *b - 2 * (*m);
		++b, ++m;
	}
}

int main() {
	int n = nxt(), m = nxt();
	vector<vector<pair<int, int>>> g(n);
	vector<int> w(m);
	for (int i = 0; i < m; ++i) {
		itn u = nxt() - 1, v = nxt() - 1;
		w[i] = nxt();
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}

	vector<int> huili;
	vector<char> used(n);
	vector<pair<int, int>> order;
	function<void(int, int)> dfs = [&](int v, int p) {
		used[v] = 1;
		for (const auto& [to, id] : g[v]) {
			if (id == p) {
				continue;
			}
			if (used[to] == 1) {
				continue;
			} else if (used[to]) {
				huili.push_back(id);
			} else {
				dfs(to, id);
			}
		}
		if (p > -1) {
			order.push_back({v, p});
		}
		used[v] = 2;
	};

	dfs(0, -1);
	vector<long long> shit(m);
	for (int x : huili) {
		shit[x] = rand() % 1000000000;
		shit[x] <<= 32;
		shit[x] |= rand();
	}
	for (const auto& [v, id] : order) {
		for (const auto& [to, idx] : g[v]) {
			assert(to > -1);
			if (id == idx) {
				continue;
			}
			shit[id] ^= shit[idx];
		}
	}

	vector<char> bridges(m);
	int off = 0;
	for (int i = 0; i < m; ++i) {
		bridges[i] = (shit[i] == 0);
		off ^= w[i];
	}

	used.assign(n, 0);
	a[off] = 1;

	const int mod = 1000000007;
	int d2 = 1;
	for (int i = 0; i < L; ++i) {
		if (d2 % 2) {
			d2 += mod;
		}
		d2 /= 2;
	}
	for (int i = 0; i < n; ++i) {
		if (used[i]) {
			continue;
		}
		memset(b, 0, sizeof(b));
		vector<int> st = {i};
		used[i] = 1;
		int cn = 0;
		while (!st.empty()) {
			++cn;
			int v = st.back();
			st.pop_back();
			for (const auto& [to, id] : g[v]) {
				if (bridges[id]) {
					continue;
				}
				b[w[id]] += 1;
				if (!used[to]) {
					used[to] = 1;
					st.push_back(to);
				}
			}
		}
		if (cn == 1) {
			continue;
		}
		for (int i = 0; i < N; ++i) {
			b[i] /= 2;
		}
		wh(a, a + N);
		wh(b, b + N);
		for (int i = 0; i < N; ++i) {
			a[i] *= b[i];
			a[i] %= mod;
		}
		wh(a, a + N);
		for (int i = 0; i < N; ++i) {
			a[i] = a[i] % mod * d2 % mod;
		}
	}

	int idx = 0;
	while (a[idx] == 0) {
		++idx;
	}
	cout << idx << " " << a[idx] << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define itn int
#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())

#define random_shuffle(...) shuffle(__VA_ARGS__, rng)
#define rand() rng()

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int L = 17;
const int N = 1 << L;

long long a[N];
long long b[N];

void wh(long long* b, long long* e) {
	if (e == b + 1) {
		return;
	}
	long long *m = b + (e - b) / 2;
	wh(b, m);
	wh(m, e);
	while (m != e) {
		*b += *m;
		*m = *b - 2 * (*m);
		++b, ++m;
	}
}

int main() {
	int n = nxt(), m = nxt();
	vector<vector<pair<int, int>>> g(n);
	vector<int> w(m);
	for (int i = 0; i < m; ++i) {
		itn u = nxt() - 1, v = nxt() - 1;
		w[i] = nxt();
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}

	vector<int> huili;
	vector<char> used(n);
	vector<pair<int, int>> order;
	function<void(int, int)> dfs = [&](int v, int p) {
		used[v] = 1;
		for (const auto& [to, id] : g[v]) {
			if (id == p) {
				continue;
			}
			if (used[to] == 1) {
				continue;
			} else if (used[to]) {
				huili.push_back(id);
			} else {
				dfs(to, id);
			}
		}
		if (p > -1) {
			order.push_back({v, p});
		}
		used[v] = 2;
	};

	dfs(0, -1);
	vector<long long> shit(m);
	for (int x : huili) {
		shit[x] = rand() % 1000000000;
		shit[x] <<= 31;
		shit[x] |= (long long)rand() % 1000000000;
	}
	for (const auto& [v, id] : order) {
		for (const auto& [to, idx] : g[v]) {
			assert(to > -1);
			if (id == idx) {
				continue;
			}
			shit[id] ^= shit[idx];
		}
	}

	vector<char> bridges(m);
	int off = 0;
	for (int i = 0; i < m; ++i) {
		bridges[i] = (shit[i] == 0);
		off ^= w[i];
	}

	used.assign(n, 0);
	a[off] = 1;

	const int mod = 1000000007;
	int d2 = 1;
	for (int i = 0; i < L; ++i) {
		if (d2 % 2) {
			d2 += mod;
		}
		d2 /= 2;
	}
	for (int i = 0; i < n; ++i) {
		if (used[i]) {
			continue;
		}
		memset(b, 0, sizeof(b));
		vector<int> st = {i};
		used[i] = 1;
		int cn = 0;
		while (!st.empty()) {
			++cn;
			int v = st.back();
			st.pop_back();
			for (const auto& [to, id] : g[v]) {
				if (bridges[id]) {
					continue;
				}
				b[w[id]] += 1;
				if (!used[to]) {
					used[to] = 1;
					st.push_back(to);
				}
			}
		}
		if (cn == 1) {
			continue;
		}
		for (int i = 0; i < N; ++i) {
			b[i] /= 2;
		}
		wh(a, a + N);
		wh(b, b + N);
		for (int i = 0; i < N; ++i) {
			a[i] *= b[i];
			a[i] %= mod;
		}
		wh(a, a + N);
		for (int i = 0; i < N; ++i) {
			a[i] = a[i] % mod * d2 % mod;
		}
	}

	int idx = 0;
	while (a[idx] == 0) {
		++idx;
	}
	cout << idx << " " << a[idx] << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define itn int
#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())

#define random_shuffle(...) shuffle(__VA_ARGS__, rng)
#define rand() rng()

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int L = 3;
const int N = 1 << L;

long long a[N];
long long b[N];

void wh(long long* b, long long* e) {
	if (e == b + 1) {
		return;
	}
	long long *m = b + (e - b) / 2;
	wh(b, m);
	wh(m, e);
	while (m != e) {
		*b += *m;
		*m = *b - 2 * (*m);
		++b, ++m;
	}
}

int main() {
	int n = nxt(), m = nxt();
	vector<vector<pair<int, int>>> g(n);
	vector<int> w(m);
	for (int i = 0; i < m; ++i) {
		itn u = nxt() - 1, v = nxt() - 1;
		w[i] = nxt();
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}

	vector<int> huili;
	vector<char> used(n);
	vector<pair<int, int>> order;
	function<void(int, int)> dfs = [&](int v, int p) {
		used[v] = 1;
		for (const auto& [to, id] : g[v]) {
			if (id == p) {
				continue;
			}
			if (used[to] == 1) {
				continue;
			} else if (used[to]) {
				huili.push_back(id);
			} else {
				dfs(to, id);
			}
		}
		if (p > -1) {
			order.push_back({v, p});
		}
		used[v] = 2;
	};

	dfs(0, -1);
	vector<long long> shit(m);
	for (int x : huili) {
		shit[x] = rand() % 1000000000;
		shit[x] <<= 32;
		shit[x] |= rand();
	}
	for (const auto& [v, id] : order) {
		for (const auto& [to, idx] : g[v]) {
			assert(to > -1);
			if (id == idx) {
				continue;
			}
			shit[id] ^= shit[idx];
		}
	}

	vector<char> bridges(m);
	int off = 0;
	for (int i = 0; i < m; ++i) {
		bridges[i] = (shit[i] == 0);
		off ^= w[i];
	}

	used.assign(n, 0);
	a[off] = 1;

	const int mod = 1000000007;
	int d2 = 1;
	for (int i = 0; i < L; ++i) {
		if (d2 % 2) {
			d2 += mod;
		}
		d2 /= 2;
	}
	for (int i = 0; i < n; ++i) {
		if (used[i]) {
			continue;
		}
		memset(b, 0, sizeof(b));
		vector<int> st = {i};
		used[i] = 1;
		while (!st.empty()) {
			int v = st.back();
			st.pop_back();
			for (const auto& [to, id] : g[v]) {
				if (bridges[id]) {
					continue;
				}
				b[w[id]] += 1;
				if (!used[to]) {
					used[to] = 1;
					st.push_back(to);
				}
			}
		}
		for (int i = 0; i < N; ++i) {
			b[i] /= 2;
		}
		wh(a, a + N);
		wh(b, b + N);
		for (int i = 0; i < N; ++i) {
			a[i] *= b[i];
			a[i] %= mod;
		}
		wh(a, a + N);
		for (int i = 0; i < N; ++i) {
			a[i] = a[i] % mod * d2 % mod;
		}
	}

	int idx = 0;
	while (a[idx] == 0) {
		++idx;
	}
	cout << idx << " " << a[idx] << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define itn int
#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())

#define random_shuffle(...) shuffle(__VA_ARGS__, rng)
#define rand() rng()

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int L = 17;
const int N = 1 << L;

long long a[N];
long long aa[N];
long long b[N];
long long bb[N];

void wh(long long* b, long long* e) {
	if (e == b + 1) {
		return;
	}
	long long *m = b + (e - b) / 2;
	wh(b, m);
	wh(m, e);
	while (m != e) {
		*b += *m;
		*m = *b - 2 * (*m);
		++b, ++m;
	}
}

vector<pair<int, int>> g[N];
vector<int> huili;
vector<char> used;
vector<pair<int, int>> order;

void dfs(int v, int p) {
	used[v] = 1;
	for (const auto& [to, id] : g[v]) {
		if (id == p) {
			continue;
		}
		if (used[to] == 1) {
			continue;
		} else if (used[to]) {
			huili.push_back(id);
		} else {
			dfs(to, id);
		}
	}
	if (p > -1) {
		order.push_back({v, p});
	}
	used[v] = 2;
}

int main() {
	int n = nxt(), m = nxt();
	vector<int> w(m);
	for (int i = 0; i < m; ++i) {
		itn u = nxt() - 1, v = nxt() - 1;
		w[i] = nxt();
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}

	used.assign(n, 0);

	dfs(0, -1);
	vector<long long> shit(m);
	for (int x : huili) {
		shit[x] = rand() % 1000000000;
		shit[x] <<= 31;
		shit[x] |= (long long)rand() % 1000000000;
	}
	for (const auto& [v, id] : order) {
		for (const auto& [to, idx] : g[v]) {
			assert(to > -1);
			if (id == idx) {
				continue;
			}
			shit[id] ^= shit[idx];
		}
	}

	vector<char> bridges(m);
	int off = 0;
	for (int i = 0; i < m; ++i) {
		bridges[i] = (shit[i] == 0);
		off ^= w[i];
	}

	used.assign(n, 0);
	a[off] = 1;
	aa[off] = 1;

	const int mod = 1000000007;
	int d2 = 1;
	for (int i = 0; i < L; ++i) {
		if (d2 % 2) {
			d2 += mod;
		}
		d2 /= 2;
	}
	for (int i = 0; i < n; ++i) {
		if (used[i]) {
			continue;
		}
		vector<int> st = {i};
		used[i] = 1;
		int cn = 0;
		while (!st.empty()) {
			++cn;
			int v = st.back();
			st.pop_back();
			for (const auto& [to, id] : g[v]) {
				if (bridges[id]) {
					continue;
				}
				b[w[id]] += 1;
				if (!used[to]) {
					used[to] = 1;
					st.push_back(to);
				}
			}
		}
		if (cn == 1) {
			continue;
		}
		for (int i = 0; i < N; ++i) {
			b[i] /= 2;
			bb[i] = b[i];
		}
		wh(a, a + N);
		wh(b, b + N);
		wh(aa, aa + N);
		wh(bb, bb + N);
		for (int i = 0; i < N; ++i) {
			a[i] %= mod;
			b[i] %= mod;
			if (a[i] < 0) {
				a[i] += mod;
			}
			if (b[i] < 0) {
				b[i] += mod;
			}
			a[i] *= b[i];
			a[i] %= mod;
			aa[i] *= bb[i];
		}
		wh(a, a + N);
		wh(aa, aa + N);
		for (int i = 0; i < N; ++i) {
			a[i] = a[i] % mod * d2 % mod;
			if (a[i] < 0) {
				a[i] += mod;
			}
			aa[i] = min(aa[i], 1ll);
		}
		memset(b, 0, sizeof(b));
	}

	int idx = 0;
	while (a[idx] == 0 && aa[idx] == 0) {
		++idx;
	}
	cout << idx << " " << a[idx] << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define itn int
#define all(x) (x).begin(), (x).end()
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())

#define random_shuffle(...) shuffle(__VA_ARGS__, rng)
#define rand() rng()

using namespace std;

inline int nxt() {
	int x;
	scanf("%d", &x);
	return x;
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int L = 17;
const int N = 1 << L;

long long a[N];
long long b[N];

void wh(long long* b, long long* e) {
	if (e == b + 1) {
		return;
	}
	long long *m = b + (e - b) / 2;
	wh(b, m);
	wh(m, e);
	while (m != e) {
		*b += *m;
		*m = *b - 2 * (*m);
		++b, ++m;
	}
}

vector<pair<int, int>> g[N];
vector<int> huili;
vector<char> used;
vector<pair<int, int>> order;

void dfs(int v, int p) {
	used[v] = 1;
	for (const auto& [to, id] : g[v]) {
		if (id == p) {
			continue;
		}
		if (used[to] == 1) {
			continue;
		} else if (used[to]) {
			huili.push_back(id);
		} else {
			dfs(to, id);
		}
	}
	if (p > -1) {
		order.push_back({v, p});
	}
	used[v] = 2;
}

int main() {
	int n = nxt(), m = nxt();
	vector<int> w(m);
	for (int i = 0; i < m; ++i) {
		itn u = nxt() - 1, v = nxt() - 1;
		w[i] = nxt();
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}

	used.assign(n, 0);

	dfs(0, -1);
	vector<long long> shit(m);
	for (int x : huili) {
		shit[x] = rand() % 1000000000;
		shit[x] <<= 31;
		shit[x] |= (long long)rand() % 1000000000;
	}
	for (const auto& [v, id] : order) {
		for (const auto& [to, idx] : g[v]) {
			assert(to > -1);
			if (id == idx) {
				continue;
			}
			shit[id] ^= shit[idx];
		}
	}

	vector<char> bridges(m);
	int off = 0;
	for (int i = 0; i < m; ++i) {
		bridges[i] = (shit[i] == 0);
		off ^= w[i];
	}

	used.assign(n, 0);
	a[off] = 1;

	const int mod = 1000000007;
	int d2 = 1;
	for (int i = 0; i < L; ++i) {
		if (d2 % 2) {
			d2 += mod;
		}
		d2 /= 2;
	}
	for (int i = 0; i < n; ++i) {
		if (used[i]) {
			continue;
		}
		vector<int> st = {i};
		used[i] = 1;
		int cn = 0;
		while (!st.empty()) {
			++cn;
			int v = st.back();
			st.pop_back();
			for (const auto& [to, id] : g[v]) {
				if (bridges[id]) {
					continue;
				}
				b[w[id]] += 1;
				if (!used[to]) {
					used[to] = 1;
					st.push_back(to);
				}
			}
		}
		if (cn == 1) {
			continue;
		}
		for (int i = 0; i < N; ++i) {
			b[i] /= 2;
		}
		wh(a, a + N);
		wh(b, b + N);
		for (int i = 0; i < N; ++i) {
			a[i] %= mod;
			b[i] %= mod;
			a[i] *= b[i];
			a[i] %= mod;
		}
		wh(a, a + N);
		for (int i = 0; i < N; ++i) {
			a[i] = a[i] % mod * d2 % mod;
		}
		memset(b, 0, sizeof(b));
	}

	int idx = 0;
	while (a[idx] == 0) {
		++idx;
	}
	cout << idx << " " << a[idx] << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define int long long

#define pii pair<int, int>

#define x1 x1228
#define y1 y1228

#define left left228
#define right right228

#define pb push_back
#define eb emplace_back

#define mp make_pair

#define ff first
#define ss second

#define matr vector<vector<int> >

#define all(x) x.begin(), x.end()

using namespace std;
typedef long long ll;
typedef long double ld;

const int maxn = 3e5 + 7, mod = 1e9 + 7, inf = 1e18, MAXN = 1e6 + 7;
const double eps = 1e-9;
mt19937 rnd(time(0));
int n, m;
int dst[maxn];
vector<pii> gr[maxn];
set<pii> edge;
map<pii, int> Edge;
int p[maxn], used[maxn];
int ptr = 0;
vector<int> cycle[maxn];
vector<int> val[maxn];

void dfs(int u, int pr, int depth) {
    dst[u] = depth;
    p[u] = pr;
    used[u] = 1;
    for (auto v : gr[u]) {
        if (!used[v.ff]) {
            dfs(v.ff, u, depth + 1);
        }  else if (v.ff != pr && dst[u] >= dst[v.ff]) {
            int pp = u;
            while (pp != v.ff) {
                cycle[ptr].pb(pp);
                pp = p[pp];
            }
            cycle[ptr++].pb(v.ff);
        }
    }
}

const int K = 1<<17;
const int mod1 = 1000000007;
const int mod2 = 998244353;

int sum(int x, int y){
    if (x + y < 0) return x+y+mod1;
    if (x+y >= mod1) return x+y-mod1;
    return x+y;
}

int mult(int x, int y){
    return ((ll) x * (ll) y) % (ll) mod1;
}

vector<int> hadamard(vector<int> v){
    for (int step=K; step > 1; step /= 2){
        for (int start=0; start < K; start += step){
            for (int w=0; w < step/2; w++){
                int F = sum(v[start+w], v[start+step/2+w]);
                int S = sum(v[start+w], -v[start+step/2+w]);
                //cout << v[start+w] << " " << v[start+step/2+w] << " " << F << endl;
                v[start + w] = F;
                v[start+step/2+w] = S;
            }
        }
    }
    return v;
}

int pw(int a, int b){
    if (b==0) return 1;
    if (b==1) return a%mod1;
    if (b%2) return mult(a, pw(a, b-1));
    int R = pw(a, b/2);
    return mult(R, R);
}

int rev1 = pw(K, mod1-2);

vector<int> mult(vector<int> v, vector<int> u){
    v = hadamard(v), u = hadamard(u);
    for (int i=0; i < K; i++) v[i] = mult(v[i], u[i]);
    v = hadamard(v);
    for (int i=0; i < K; i++){
        v[i] = mult(v[i], rev1);
    }
    //cout << v[0] << endl;
    return v;
}

int sum2(int x, int y){
    if (x + y < 0) return x+y+mod2;
    if (x+y >= mod2) return x+y-mod2;
    return x+y;
}

int mult2(int x, int y){
    return ((ll) x * (ll) y) % (ll) mod2;
}

vector<int> hadamard2(vector<int> v){
    for (int step=K; step > 1; step /= 2){
        for (int start=0; start < K; start += step){
            for (int w=0; w < step/2; w++){
                int F = sum2(v[start+w], v[start+step/2+w]);
                int S = sum2(v[start+w], -v[start+step/2+w]);
                //cout << v[start+w] << " " << v[start+step/2+w] << " " << F << endl;
                v[start + w] = F;
                v[start+step/2+w] = S;
            }
        }
    }
    return v;
}

int pw2(int a, int b){
    if (b==0) return 1;
    if (b==1) return a%mod2;
    if (b%2) return mult2(a, pw2(a, b-1));
    int R = pw2(a, b/2);
    return mult2(R, R);
}

int rev2 = pw2(K, mod2-2);

vector<int> mult2(vector<int> v, vector<int> u){
    v = hadamard2(v), u = hadamard2(u);
    for (int i=0; i < K; i++) v[i] = mult2(v[i], u[i]);
    v = hadamard2(v);
    for (int i=0; i < K; i++){
        v[i] = mult2(v[i], rev2);
    }
    //cout << v[0] << endl;
    return v;
}

void solve() {
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        int a, b, c; cin >> a >> b >> c, --a, --b;
        if (a > b) swap(a, b);
        edge.insert(mp(a, b));
        Edge[mp(a, b)] = c;
        gr[a].eb(b, c);
        gr[b].eb(a, c);
    }
    dfs(0, 0, 0);
    int RES = 0;
    for (int idx = 0; idx < ptr; ++idx) {
        vector<int> nw = cycle[idx];
        nw.pb(nw[0]);
        for (int i = 1; i < nw.size(); ++i) {
            int a = nw[i - 1], b = nw[i];
            if (a > b) swap(a, b);
            val[idx].pb(Edge[mp(a, b)]);
            edge.erase(mp(a, b));
        }
    }
    for (auto v : edge) {
        RES ^= Edge[mp(v.ff, v.ss)];
    }
    for (int i = 0; i < ptr; ++i) {
        int pp = 0;
        vector<int> nw = val[i];
        for (auto v : nw) pp ^= v;
        for (int j = 0; j < nw.size(); ++j) {
            nw[j] = (pp ^ nw[j]);
        }
        val[i] = nw;
    }
    vector<int> nw(K), nww(K);
    nw[0] = 1;
    nww[0] = 1;
    for (int i = 0; i < ptr; ++i) {
        vector<int> cur(K, 0);
        for (auto v : val[i]) cur[v]++;
        nw = mult(nw, cur);
        nww = mult2(nww, cur);
    }
    int mn = inf, cnt = 0;
    for (int i = 0; i < K; ++i) {
        if (nw[i] == 0 && nww[i] == 0) continue;
        if ((i ^ RES) < mn) {
            mn = (i ^ RES);
            cnt = nw[i];
        } else if ((i ^ RES) == mn) {
            cnt += nw[i];
            cnt %= mod1;
        }
    }
    cout << mn << " " << cnt << '\n';
}

signed main() {
#ifdef LOCAL
    freopen("TASK.in", "r", stdin);
    freopen("TASK.out", "w", stdout);
#else

#endif // LOCAL
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(20);
    cout << fixed;
    int t = 1;
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}


#include <bits/stdc++.h>

//#define int long long

#define pii pair<int, int>

#define x1 x1228
#define y1 y1228

#define left left228
#define right right228

#define pb push_back
#define eb emplace_back

#define mp make_pair

#define ff first
#define ss second

#define matr vector<vector<int> >

#define all(x) x.begin(), x.end()

using namespace std;
typedef long long ll;
typedef long double ld;

const int maxn = 3e5 + 7, mod = 1e9 + 7, inf = 1e9, MAXN = 1e6 + 7;
const double eps = 1e-9;
mt19937 rnd(time(0));
int n, m;
int dst[maxn];
vector<pii> gr[maxn];
set<pii> edge;
map<pii, int> Edge;
int p[maxn], used[maxn];
int ptr = 0;
vector<int> cycle[maxn];
vector<int> val[maxn];

void dfs(int u, int pr, int depth) {
    dst[u] = depth;
    p[u] = pr;
    used[u] = 1;
    for (auto v : gr[u]) {
        if (!used[v.ff]) {
            dfs(v.ff, u, depth + 1);
        }  else if (v.ff != pr && dst[u] >= dst[v.ff]) {
            int pp = u;
            while (pp != v.ff) {
                cycle[ptr].pb(pp);
                pp = p[pp];
            }
            cycle[ptr++].pb(v.ff);
        }
    }
}

const int K = 1<<17;
const int mod1 = 1000000007;
const int mod2 = 998244353;

int sum(int x, int y){
    if (x + y < 0) return x+y+mod1;
    if (x+y >= mod1) return x+y-mod1;
    return x+y;
}

int mult(int x, int y){
    return ((ll) x * (ll) y) % (ll) mod1;
}

vector<int> hadamard(vector<int> v){
    for (int step=K; step > 1; step /= 2){
        for (int start=0; start < K; start += step){
            for (int w=0; w < step/2; w++){
                int F = sum(v[start+w], v[start+step/2+w]);
                int S = sum(v[start+w], -v[start+step/2+w]);
                //cout << v[start+w] << " " << v[start+step/2+w] << " " << F << endl;
                v[start + w] = F;
                v[start+step/2+w] = S;
            }
        }
    }
    return v;
}

int pw(int a, int b){
    if (b==0) return 1;
    if (b==1) return a%mod1;
    if (b%2) return mult(a, pw(a, b-1));
    int R = pw(a, b/2);
    return mult(R, R);
}

int rev1 = pw(K, mod1-2);

vector<int> mult(vector<int> v, vector<int> u){
    v = hadamard(v), u = hadamard(u);
    for (int i=0; i < K; i++) v[i] = mult(v[i], u[i]);
    v = hadamard(v);
    for (int i=0; i < K; i++){
        v[i] = mult(v[i], rev1);
    }
    //cout << v[0] << endl;
    return v;
}

int sum2(int x, int y){
    if (x + y < 0) return x+y+mod2;
    if (x+y >= mod2) return x+y-mod2;
    return x+y;
}

int mult2(int x, int y){
    return ((ll) x * (ll) y) % (ll) mod2;
}

vector<int> hadamard2(vector<int> v){
    for (int step=K; step > 1; step /= 2){
        for (int start=0; start < K; start += step){
            for (int w=0; w < step/2; w++){
                int F = sum2(v[start+w], v[start+step/2+w]);
                int S = sum2(v[start+w], -v[start+step/2+w]);
                //cout << v[start+w] << " " << v[start+step/2+w] << " " << F << endl;
                v[start + w] = F;
                v[start+step/2+w] = S;
            }
        }
    }
    return v;
}

int pw2(int a, int b){
    if (b==0) return 1;
    if (b==1) return a%mod2;
    if (b%2) return mult2(a, pw2(a, b-1));
    int R = pw2(a, b/2);
    return mult2(R, R);
}

int rev2 = pw2(K, mod2-2);

vector<int> mult2(vector<int> v, vector<int> u){
    v = hadamard2(v), u = hadamard2(u);
    for (int i=0; i < K; i++) v[i] = mult2(v[i], u[i]);
    v = hadamard2(v);
    for (int i=0; i < K; i++){
        v[i] = mult2(v[i], rev2);
    }
    //cout << v[0] << endl;
    return v;
}

void solve() {
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        int a, b, c; cin >> a >> b >> c, --a, --b;
        if (a > b) swap(a, b);
        edge.insert(mp(a, b));
        Edge[mp(a, b)] = c;
        gr[a].eb(b, c);
        gr[b].eb(a, c);
    }
    dfs(0, 0, 0);
    int RES = 0;
    for (int idx = 0; idx < ptr; ++idx) {
        vector<int> nw = cycle[idx];
        nw.pb(nw[0]);
        for (int i = 1; i < nw.size(); ++i) {
            int a = nw[i - 1], b = nw[i];
            if (a > b) swap(a, b);
            val[idx].pb(Edge[mp(a, b)]);
            edge.erase(mp(a, b));
        }
    }
    for (auto v : edge) {
        RES ^= Edge[mp(v.ff, v.ss)];
    }
    for (int i = 0; i < ptr; ++i) {
        int pp = 0;
        vector<int> nw = val[i];
        for (auto v : nw) pp ^= v;
        for (int j = 0; j < nw.size(); ++j) {
            nw[j] = (pp ^ nw[j]);
        }
        val[i] = nw;
    }
    vector<int> nw(K), nww(K);
    nw[0] = 1;
    nww[0] = 1;
    for (int i = 0; i < ptr; ++i) {
        vector<int> cur(K, 0);
        for (auto v : val[i]) cur[v]++;
        nw = mult(nw, cur);
        nww = mult2(nww, cur);
    }
    int mn = inf, cnt = 0;
    for (int i = 0; i < K; ++i) {
        if (nw[i] == 0 && nww[i] == 0) continue;
        if ((i ^ RES) < mn) {
            mn = (i ^ RES);
            cnt = nw[i];
        } else if ((i ^ RES) == mn) {
            cnt += nw[i];
            cnt %= mod1;
        }
    }
    cout << mn << " " << cnt << '\n';
}

signed main() {
#ifdef LOCAL
    freopen("TASK.in", "r", stdin);
    freopen("TASK.out", "w", stdout);
#else

#endif // LOCAL
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(20);
    cout << fixed;
    int t = 1;
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}


#include <bits/stdc++.h>

#define int long long

#define pii pair<int, int>

#define x1 x1228
#define y1 y1228

#define left left228
#define right right228

#define pb push_back
#define eb emplace_back

#define mp make_pair

#define ff first
#define ss second

#define matr vector<vector<int> >

#define all(x) x.begin(), x.end()

using namespace std;
typedef long long ll;
typedef long double ld;

const int maxn = 3e5 + 7, mod = 1e9 + 7, inf = 1e18, MAXN = 1e6 + 7;
const double eps = 1e-9;
mt19937 rnd(time(0));
int n, m;
int dst[maxn];
vector<pii> gr[maxn];
set<pii> edge;
map<pii, int> Edge;
int p[maxn], used[maxn];
int ptr = 0;
vector<int> cycle[maxn];
vector<int> val[maxn];

void dfs(int u, int pr, int depth) {
    dst[u] = depth;
    p[u] = pr;
    used[u] = 1;
    for (auto v : gr[u]) {
        if (!used[v.ff]) {
            dfs(v.ff, u, depth + 1);
        }  else if (v.ff != pr && dst[u] >= dst[v.ff]) {
            int pp = u;
            while (pp != v.ff) {
                cycle[ptr].pb(pp);
                pp = p[pp];
            }
            cycle[ptr++].pb(v.ff);
        }
    }
}

const int K = 1<<17;
const int mod1 = 1000000007;
const int mod2 = 998244353;

int sum(int x, int y){
    if (x + y < 0) return x+y+mod1;
    if (x+y >= mod1) return x+y-mod1;
    return x+y;
}

int mult(int x, int y){
    return ((ll) x * (ll) y) % (ll) mod1;
}

vector<int> hadamard(vector<int> v){
    for (int step=K; step > 1; step /= 2){
        for (int start=0; start < K; start += step){
            for (int w=0; w < step/2; w++){
                int F = sum(v[start+w], v[start+step/2+w]);
                int S = sum(v[start+w], -v[start+step/2+w]);
                //cout << v[start+w] << " " << v[start+step/2+w] << " " << F << endl;
                v[start + w] = F;
                v[start+step/2+w] = S;
            }
        }
    }
    return v;
}

int pw(int a, int b){
    if (b==0) return 1;
    if (b==1) return a%mod1;
    if (b%2) return mult(a, pw(a, b-1));
    int R = pw(a, b/2);
    return mult(R, R);
}

int rev1 = pw(K, mod1-2);

vector<int> mult(vector<int> v, vector<int> u){
    v = hadamard(v), u = hadamard(u);
    for (int i=0; i < K; i++) v[i] = mult(v[i], u[i]);
    v = hadamard(v);
    for (int i=0; i < K; i++){
        v[i] = mult(v[i], rev1);
    }
    //cout << v[0] << endl;
    return v;
}

int sum2(int x, int y){
    if (x + y < 0) return x+y+mod2;
    if (x+y >= mod2) return x+y-mod2;
    return x+y;
}

int mult2(int x, int y){
    return ((ll) x * (ll) y) % (ll) mod2;
}

vector<int> hadamard2(vector<int> v){
    for (int step=K; step > 1; step /= 2){
        for (int start=0; start < K; start += step){
            for (int w=0; w < step/2; w++){
                int F = sum2(v[start+w], v[start+step/2+w]);
                int S = sum2(v[start+w], -v[start+step/2+w]);
                //cout << v[start+w] << " " << v[start+step/2+w] << " " << F << endl;
                v[start + w] = F;
                v[start+step/2+w] = S;
            }
        }
    }
    return v;
}

int pw2(int a, int b){
    if (b==0) return 1;
    if (b==1) return a%mod2;
    if (b%2) return mult2(a, pw2(a, b-1));
    int R = pw2(a, b/2);
    return mult2(R, R);
}

int rev2 = pw2(K, mod2-2);

vector<int> mult2(vector<int> v, vector<int> u){
    v = hadamard2(v), u = hadamard2(u);
    for (int i=0; i < K; i++) v[i] = mult2(v[i], u[i]);
    v = hadamard2(v);
    for (int i=0; i < K; i++){
        v[i] = mult2(v[i], rev2);
    }
    //cout << v[0] << endl;
    return v;
}

void solve() {
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        int a, b, c; cin >> a >> b >> c, --a, --b;
        if (a > b) swap(a, b);
        edge.insert(mp(a, b));
        Edge[mp(a, b)] = c;
        gr[a].eb(b, c);
        gr[b].eb(a, c);
    }
    dfs(0, 0, 0);
    int RES = 0;
    for (int idx = 0; idx < ptr; ++idx) {
        vector<int> nw = cycle[idx];
        nw.pb(nw[0]);
        for (int i = 1; i < nw.size(); ++i) {
            int a = nw[i - 1], b = nw[i];
            if (a > b) swap(a, b);
            val[idx].pb(Edge[mp(a, b)]);
            edge.erase(mp(a, b));
        }
    }
    for (auto v : edge) {
        RES ^= Edge[mp(v.ff, v.ss)];
    }
    for (int i = 0; i < ptr; ++i) {
        int pp = 0;
        vector<int> nw = val[i];
        for (auto v : nw) pp ^= v;
        for (int j = 0; j < nw.size(); ++j) {
            nw[j] = (pp ^ nw[j]);
        }
        val[i] = nw;
    }
    vector<int> nw(K), nww(K);
    nw[0] = 1;
    nww[0] = 1;
    for (int i = 0; i < ptr; ++i) {
        vector<int> cur(K, 0);
        for (auto v : val[i]) cur[v]++;
        nw = mult(nw, cur);
        nww = mult(nww, cur);
    }
    int mn = inf, cnt = 0;
    for (int i = 0; i < K; ++i) {
        if (nw[i] == 0 && nww[i] == 0) continue;
        if ((i ^ RES) < mn) {
            mn = (i ^ RES);
            cnt = (i ^ RES);
        } else if ((i ^ RES) == mn) {
            cnt += nw[i];
            cnt %= mod1;
        }
    }
    cout << mn << " " << cnt << '\n';
}

signed main() {
#ifdef LOCAL
    freopen("TASK.in", "r", stdin);
    freopen("TASK.out", "w", stdout);
#else

#endif // LOCAL
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(20);
    cout << fixed;
    int t = 1;
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}


#include <bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define st first
#define nd second
#define rd third
#define FOR(i, a, b) for(int i =(a); i <=(b); ++i)
#define RE(i, n) FOR(i, 1, n)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define REP(i, n) for(int i = 0;i <(n); ++i)
#define VAR(v, i) __typeof(i) v=(i)
#define FORE(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define __builtin_ctz __builtin_ctzll
#define __builtin_clz __builtin_clzll
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<typename TH> void _dbg(const char* sdbg, TH h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename TH, typename... TA> void _dbg(const char* sdbg, TH h, TA... t) {
  while(*sdbg != ',') { cerr<<*sdbg++; } cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}
#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(itt, (x)) cerr <<*itt <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define cerr if(0)cout
#endif
#define next ____next
#define prev ____prev
#define left ____left
#define hash ____hash
typedef long long ll;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VLL;
typedef vector<pair<int, int> > VPII;
typedef vector<pair<ll, ll> > VPLL;

template<class C> void mini(C&a4, C b4){a4=min(a4, b4); }
template<class C> void maxi(C&a4, C b4){a4=max(a4, b4); }
template<class T1, class T2>
ostream& operator<< (ostream &out, pair<T1, T2> pair) { return out << "(" << pair.first << ", " << pair.second << ")";}
template<class A, class B, class C> struct Triple { A first; B second; C third;
  bool operator<(const Triple& t) const { if (st != t.st) return st < t.st; if (nd != t.nd) return nd < t.nd; return rd < t.rd; } };
template<class T> void ResizeVec(T&, vector<int>) {}
template<class T> void ResizeVec(vector<T>& vec, vector<int> sz) {
  vec.resize(sz[0]); sz.erase(sz.begin()); if (sz.empty()) { return; }
  for (T& v : vec) { ResizeVec(v, sz); }
}
typedef Triple<int, int, int> TIII;
template<class A, class B, class C>
ostream& operator<< (ostream &out, Triple<A, B, C> t) { return out << "(" << t.st << ", " << t.nd << ", " << t.rd << ")"; }
template<class T> ostream& operator<<(ostream& out, vector<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class T> ostream& operator<<(ostream& out, set<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class L, class R> ostream& operator<<(ostream& out, map<L, R> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }

const int M = 1 << 17;
VVI cycles;
VPII stos;
VPII slo[M];
int vis[M];
int d;
int pre[M];
void Dfs(int v) {
  vis[v] = 1;
  pre[v] = d++;
  for (auto e : slo[v]) {
    int nei = e.st;
    int w = e.nd;
    if (vis[nei]) {
      if (SZ(stos) >= 2 && stos[SZ(stos) - 2].st == nei) { continue; }
      if (pre[nei] > pre[v]) { continue; }
      debug(nei, v);
      cycles.PB(VI{w});
      FORD (ind, SZ(stos) - 1, 0){
        if (stos[ind].st == nei) { break; }
        cycles.back().PB(stos[ind].nd);
      }
      continue;
    }
    stos.PB({nei, w});
    Dfs(nei);
    stos.pop_back();
  }
}
int MOD = 1e9 + 7;
const int INV2 = (MOD + 1) / 2;
void SelfMod(int& a) {
  while (a >= MOD) {
    a -= MOD;
  }
}
void Dziel(int& a) {
  if (a % 2 == 0) {
    a /= 2;
  } else {
    a = (a + MOD) / 2;
  }
}
//const int N = 1 << 20;
// Transforms the interval [x, y) in a.
void transform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  transform(x, z, a);
  transform(z, y, a);
  for (int i=x; i<z; i++) {
    int x1 = a[i];
    int x2 = a[i+l2];
    a[i] = (x1 - x2 + MOD);
    a[i+l2] = (x1 + x2);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
  }
}
// Reverses the transform in
// the interval [x, y) in a.
void untransform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  for (int i=x; i<z; i++) {
    long long y1 = a[i];
    long long y2 = a[i+l2];
    // x1 - x2 = y1
    // x1 + x2 = y2
    // 2 * x1  = y1 + y2
    // 2 * x2  = y2 - y1

    // In order to solve those equations, we need to divide by 2
    // But we are performing operations modulo 1000000007
    // that needs us to find the modular multiplicative inverse of 2.
    // That is saved in the INV2 variable.

    a[i] = (y1 + y2);
    a[i+l2] = (y2 - y1 + MOD);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
    Dziel(a[i]);
    Dziel(a[i + l2]);
  }
  untransform(x, z, a);
  untransform(z, y, a);
}

// void Mnoz(VI& A, VI& B) {
//   transform(0, M, &A[0]);
//   transform(0, M, &B[0]);
//   REP (i, M) {
//     A[i] = (long long) A[i] * B[i] % MOD;
//   }
//   untransform(0, M, &A[0]);
//   //return A;
// }

int32_t main() {

  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin.tie(0);
  //double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;

  int n, m;
  cin>>n>>m;
  int xorr = 0;
  RE (i, m) {
    int a, b, w;
    cin>>a>>b>>w;
    xorr ^= w;
    slo[a].PB({b, w});
    slo[b].PB({a, w});
  }
  stos.PB({1, 0});
  Dfs(1);
  debug(cycles);
  VI cur(M), cur2(M);
  cur[0] = 1;
  transform(0, M, &cur[0]);
  MOD = 1e9 + 9;
  cur2[0] = 1;
  transform(0, M, &cur2[0]);
  for (auto cycle : cycles) {
    VI cyc_cnt(M);
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = 1e9 + 7;
    transform(0, M, &cyc_cnt[0]);
    REP (i, M) {
      cur[i] = 1ll * cur[i] * cyc_cnt[i] % MOD;
    }
    REP (i, M) {
      cyc_cnt[i] = 0;
    }
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = 1e9 + 9;
    transform(0, M, &cyc_cnt[0]);
    REP (i, M) {
      cur2[i] = 1ll * cur2[i] * cyc_cnt[i] % MOD;
    }
    //Mnoz(cur, cyc_cnt);
//     MOD = 1e9 + 9;
//     cur2 = Mnoz(cur2, cyc_cnt);
  }
  int min_res = 1e9;
  int wh_min = -1;
  MOD = 1e9 + 7;
  untransform(0, M, &cur[0]);
  MOD = 1e9 + 9;
  untransform(0, M, &cur2[0]);
  REP (i, M) {
    if (cur[i] /*&& cur2[i]*/) {
      int cand_xor = xorr ^ i;
      if (cand_xor < min_res) {
        min_res = cand_xor;
        wh_min = i;
      }
    }
  }
  cout<<min_res<<" "<<cur[wh_min]<<"\n";

  return 0;
}


#include <bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define st first
#define nd second
#define rd third
#define FOR(i, a, b) for(int i =(a); i <=(b); ++i)
#define RE(i, n) FOR(i, 1, n)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define REP(i, n) for(int i = 0;i <(n); ++i)
#define VAR(v, i) __typeof(i) v=(i)
#define FORE(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define __builtin_ctz __builtin_ctzll
#define __builtin_clz __builtin_clzll
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<typename TH> void _dbg(const char* sdbg, TH h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename TH, typename... TA> void _dbg(const char* sdbg, TH h, TA... t) {
  while(*sdbg != ',') { cerr<<*sdbg++; } cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}
#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(itt, (x)) cerr <<*itt <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define cerr if(0)cout
#endif
#define next ____next
#define prev ____prev
#define left ____left
#define hash ____hash
typedef long long ll;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VLL;
typedef vector<pair<int, int> > VPII;
typedef vector<pair<ll, ll> > VPLL;

template<class C> void mini(C&a4, C b4){a4=min(a4, b4); }
template<class C> void maxi(C&a4, C b4){a4=max(a4, b4); }
template<class T1, class T2>
ostream& operator<< (ostream &out, pair<T1, T2> pair) { return out << "(" << pair.first << ", " << pair.second << ")";}
template<class A, class B, class C> struct Triple { A first; B second; C third;
  bool operator<(const Triple& t) const { if (st != t.st) return st < t.st; if (nd != t.nd) return nd < t.nd; return rd < t.rd; } };
template<class T> void ResizeVec(T&, vector<int>) {}
template<class T> void ResizeVec(vector<T>& vec, vector<int> sz) {
  vec.resize(sz[0]); sz.erase(sz.begin()); if (sz.empty()) { return; }
  for (T& v : vec) { ResizeVec(v, sz); }
}
typedef Triple<int, int, int> TIII;
template<class A, class B, class C>
ostream& operator<< (ostream &out, Triple<A, B, C> t) { return out << "(" << t.st << ", " << t.nd << ", " << t.rd << ")"; }
template<class T> ostream& operator<<(ostream& out, vector<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class T> ostream& operator<<(ostream& out, set<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class L, class R> ostream& operator<<(ostream& out, map<L, R> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }

const int M = 1 << 17;
VVI cycles;
VPII stos;
VPII slo[M];
int vis[M];
int d;
int pre[M];
void Dfs(int v) {
  vis[v] = 1;
  pre[v] = d++;
  for (auto e : slo[v]) {
    int nei = e.st;
    int w = e.nd;
    if (vis[nei]) {
      if (SZ(stos) >= 2 && stos[SZ(stos) - 2].st == nei) { continue; }
      if (pre[nei] > pre[v]) { continue; }
      debug(nei, v);
      cycles.PB(VI{w});
      FORD (ind, SZ(stos) - 1, 0){
        if (stos[ind].st == nei) { break; }
        cycles.back().PB(stos[ind].nd);
      }
      continue;
    }
    stos.PB({nei, w});
    Dfs(nei);
    stos.pop_back();
  }
}
int MOD = 1e9 + 7;
const int M2 = 999999197;
const int INV2 = (MOD + 1) / 2;
void SelfMod(int& a) {
  while (a >= MOD) {
    a -= MOD;
  }
}
void Dziel(int& a) {
  if (a % 2 == 0) {
    a /= 2;
  } else {
    a = (a + MOD) / 2;
  }
}
//const int N = 1 << 20;
// Transforms the interval [x, y) in a.
void transform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  transform(x, z, a);
  transform(z, y, a);
  for (int i=x; i<z; i++) {
    int x1 = a[i];
    int x2 = a[i+l2];
    a[i] = (x1 - x2 + MOD);
    a[i+l2] = (x1 + x2);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
  }
}
// Reverses the transform in
// the interval [x, y) in a.
void untransform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  for (int i=x; i<z; i++) {
    long long y1 = a[i];
    long long y2 = a[i+l2];
    // x1 - x2 = y1
    // x1 + x2 = y2
    // 2 * x1  = y1 + y2
    // 2 * x2  = y2 - y1

    // In order to solve those equations, we need to divide by 2
    // But we are performing operations modulo 1000000007
    // that needs us to find the modular multiplicative inverse of 2.
    // That is saved in the INV2 variable.

    a[i] = (y1 + y2);
    a[i+l2] = (y2 - y1 + MOD);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
    Dziel(a[i]);
    Dziel(a[i + l2]);
  }
  untransform(x, z, a);
  untransform(z, y, a);
}

// void Mnoz(VI& A, VI& B) {
//   transform(0, M, &A[0]);
//   transform(0, M, &B[0]);
//   REP (i, M) {
//     A[i] = (long long) A[i] * B[i] % MOD;
//   }
//   untransform(0, M, &A[0]);
//   //return A;
// }

int32_t main() {

  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin.tie(0);
  //double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;

  int n, m;
  cin>>n>>m;
  int xorr = 0;
  RE (i, m) {
    int a, b, w;
    cin>>a>>b>>w;
    xorr ^= w;
    slo[a].PB({b, w});
    slo[b].PB({a, w});
  }
  stos.PB({1, 0});
  Dfs(1);
  debug(cycles);
  VI cur(M), cur2(M);
  cur[0] = 1;
  transform(0, M, &cur[0]);
  MOD = M2;
  cur2[0] = 1;
  transform(0, M, &cur2[0]);
  for (auto cycle : cycles) {
    VI cyc_cnt(M);
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = 1e9 + 7;
    transform(0, M, &cyc_cnt[0]);
    REP (i, M) {
      cur[i] = 1ll * cur[i] * cyc_cnt[i] % MOD;
    }
    REP (i, M) {
      cyc_cnt[i] = 0;
    }
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = M2;
    transform(0, M, &cyc_cnt[0]);
    REP (i, M) {
      cur2[i] = 1ll * cur2[i] * cyc_cnt[i] % MOD;
    }
    //Mnoz(cur, cyc_cnt);
//     MOD = M2;
//     cur2 = Mnoz(cur2, cyc_cnt);
  }
  int min_res = 1e9;
  int wh_min = -1;
  MOD = 1e9 + 7;
  untransform(0, M, &cur[0]);
  MOD = M2;
  untransform(0, M, &cur2[0]);
  if (n < 45) {
    assert(cur == cur2);
  }
  REP (i, M) {
    if (cur[i] || cur2[i]) {
      int cand_xor = xorr ^ i;
      if (cand_xor < min_res) {
        min_res = cand_xor;
        wh_min = i;
      }
    }
  }
  cout<<min_res<<" "<<cur[wh_min]<<"\n";

  return 0;
}


#include <bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define st first
#define nd second
#define rd third
#define FOR(i, a, b) for(int i =(a); i <=(b); ++i)
#define RE(i, n) FOR(i, 1, n)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define REP(i, n) for(int i = 0;i <(n); ++i)
#define VAR(v, i) __typeof(i) v=(i)
#define FORE(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define __builtin_ctz __builtin_ctzll
#define __builtin_clz __builtin_clzll
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<typename TH> void _dbg(const char* sdbg, TH h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename TH, typename... TA> void _dbg(const char* sdbg, TH h, TA... t) {
  while(*sdbg != ',') { cerr<<*sdbg++; } cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}
#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(itt, (x)) cerr <<*itt <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define cerr if(0)cout
#endif
#define next ____next
#define prev ____prev
#define left ____left
#define hash ____hash
typedef long long ll;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VLL;
typedef vector<pair<int, int> > VPII;
typedef vector<pair<ll, ll> > VPLL;

template<class C> void mini(C&a4, C b4){a4=min(a4, b4); }
template<class C> void maxi(C&a4, C b4){a4=max(a4, b4); }
template<class T1, class T2>
ostream& operator<< (ostream &out, pair<T1, T2> pair) { return out << "(" << pair.first << ", " << pair.second << ")";}
template<class A, class B, class C> struct Triple { A first; B second; C third;
  bool operator<(const Triple& t) const { if (st != t.st) return st < t.st; if (nd != t.nd) return nd < t.nd; return rd < t.rd; } };
template<class T> void ResizeVec(T&, vector<int>) {}
template<class T> void ResizeVec(vector<T>& vec, vector<int> sz) {
  vec.resize(sz[0]); sz.erase(sz.begin()); if (sz.empty()) { return; }
  for (T& v : vec) { ResizeVec(v, sz); }
}
typedef Triple<int, int, int> TIII;
template<class A, class B, class C>
ostream& operator<< (ostream &out, Triple<A, B, C> t) { return out << "(" << t.st << ", " << t.nd << ", " << t.rd << ")"; }
template<class T> ostream& operator<<(ostream& out, vector<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class T> ostream& operator<<(ostream& out, set<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class L, class R> ostream& operator<<(ostream& out, map<L, R> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }

const int M = 1 << 17;
VVI cycles;
VPII stos;
VPII slo[M];
int vis[M];
int d;
int pre[M];
void Dfs(int v) {
  vis[v] = 1;
  pre[v] = d++;
  for (auto e : slo[v]) {
    int nei = e.st;
    int w = e.nd;
    if (vis[nei]) {
      if (SZ(stos) >= 2 && stos[SZ(stos) - 2].st == nei) { continue; }
      if (pre[nei] > pre[v]) { continue; }
      debug(nei, v);
      cycles.PB(VI{w});
      FORD (ind, SZ(stos) - 1, 0){
        if (stos[ind].st == nei) { break; }
        cycles.back().PB(stos[ind].nd);
      }
      continue;
    }
    stos.PB({nei, w});
    Dfs(nei);
    stos.pop_back();
  }
}
int MOD = 1e9 + 7;
const int INV2 = (MOD + 1) / 2;
void SelfMod(int& a) {
  while (a >= MOD) {
    a -= MOD;
  }
}
void Dziel(int& a) {
  if (a % 2 == 0) {
    a /= 2;
  } else {
    a = (a + MOD) / 2;
  }
}
//const int N = 1 << 20;
// Transforms the interval [x, y) in a.
void transform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  transform(x, z, a);
  transform(z, y, a);
  for (int i=x; i<z; i++) {
    int x1 = a[i];
    int x2 = a[i+l2];
    a[i] = (x1 - x2 + MOD);
    a[i+l2] = (x1 + x2);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
  }
}
// Reverses the transform in
// the interval [x, y) in a.
void untransform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  for (int i=x; i<z; i++) {
    long long y1 = a[i];
    long long y2 = a[i+l2];
    // x1 - x2 = y1
    // x1 + x2 = y2
    // 2 * x1  = y1 + y2
    // 2 * x2  = y2 - y1

    // In order to solve those equations, we need to divide by 2
    // But we are performing operations modulo 1000000007
    // that needs us to find the modular multiplicative inverse of 2.
    // That is saved in the INV2 variable.

    a[i] = (y1 + y2);
    a[i+l2] = (y2 - y1 + MOD);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
    Dziel(a[i]);
    Dziel(a[i + l2]);
  }
  untransform(x, z, a);
  untransform(z, y, a);
}

void Mnoz(VI& A, VI& B) {
  transform(0, M, &A[0]);
  transform(0, M, &B[0]);
  REP (i, M) {
    A[i] = (long long) A[i] * B[i] % MOD;
  }
  untransform(0, M, &A[0]);
  //return A;
}

int32_t main() {

  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin.tie(0);
  //double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;

  int n, m;
  cin>>n>>m;
  int xorr = 0;
  RE (i, m) {
    int a, b, w;
    cin>>a>>b>>w;
    xorr ^= w;
    slo[a].PB({b, w});
    slo[b].PB({a, w});
  }
  stos.PB({1, 0});
  Dfs(1);
  debug(cycles);
  VI cur(M), cur2(M);
  cur[0] = 1;
  cur2[0] = 1;
  for (auto cycle : cycles) {
    VI cyc_cnt(M);
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = 1e9 + 7;
    Mnoz(cur, cyc_cnt);
//     MOD = 1e9 + 9;
//     cur2 = Mnoz(cur2, cyc_cnt);
  }
  int min_res = 1e9;
  int wh_min = -1;
  REP (i, M) {
    if (cur[i] /*&& cur2[i]*/) {
      int cand_xor = xorr ^ i;
      if (cand_xor < min_res) {
        min_res = cand_xor;
        wh_min = i;
      }
    }
  }
  cout<<min_res<<" "<<cur[wh_min]<<"\n";

  return 0;
}


#include <bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define int long long
#define st first
#define nd second
#define rd third
#define FOR(i, a, b) for(int i =(a); i <=(b); ++i)
#define RE(i, n) FOR(i, 1, n)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define REP(i, n) for(int i = 0;i <(n); ++i)
#define VAR(v, i) __typeof(i) v=(i)
#define FORE(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define __builtin_ctz __builtin_ctzll
#define __builtin_clz __builtin_clzll
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<typename TH> void _dbg(const char* sdbg, TH h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename TH, typename... TA> void _dbg(const char* sdbg, TH h, TA... t) {
  while(*sdbg != ',') { cerr<<*sdbg++; } cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}
#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(itt, (x)) cerr <<*itt <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define cerr if(0)cout
#endif
#define next ____next
#define prev ____prev
#define left ____left
#define hash ____hash
typedef long long ll;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VLL;
typedef vector<pair<int, int> > VPII;
typedef vector<pair<ll, ll> > VPLL;

template<class C> void mini(C&a4, C b4){a4=min(a4, b4); }
template<class C> void maxi(C&a4, C b4){a4=max(a4, b4); }
template<class T1, class T2>
ostream& operator<< (ostream &out, pair<T1, T2> pair) { return out << "(" << pair.first << ", " << pair.second << ")";}
template<class A, class B, class C> struct Triple { A first; B second; C third;
  bool operator<(const Triple& t) const { if (st != t.st) return st < t.st; if (nd != t.nd) return nd < t.nd; return rd < t.rd; } };
template<class T> void ResizeVec(T&, vector<int>) {}
template<class T> void ResizeVec(vector<T>& vec, vector<int> sz) {
  vec.resize(sz[0]); sz.erase(sz.begin()); if (sz.empty()) { return; }
  for (T& v : vec) { ResizeVec(v, sz); }
}
typedef Triple<int, int, int> TIII;
template<class A, class B, class C>
ostream& operator<< (ostream &out, Triple<A, B, C> t) { return out << "(" << t.st << ", " << t.nd << ", " << t.rd << ")"; }
template<class T> ostream& operator<<(ostream& out, vector<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class T> ostream& operator<<(ostream& out, set<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class L, class R> ostream& operator<<(ostream& out, map<L, R> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }

const int M = 1 << 17;
VVI cycles;
VPII stos;
VPII slo[M];
int vis[M];
int d;
int pre[M];
void Dfs(int v) {
  vis[v] = 1;
  pre[v] = d++;
  for (auto e : slo[v]) {
    int nei = e.st;
    int w = e.nd;
    if (vis[nei]) {
      if (SZ(stos) >= 2 && stos[SZ(stos) - 2].st == nei) { continue; }
      if (pre[nei] > pre[v]) { continue; }
      debug(nei, v);
      cycles.PB(VI{w});
      FORD (ind, SZ(stos) - 1, 0){
        if (stos[ind].st == nei) { break; }
        cycles.back().PB(stos[ind].nd);
      }
      continue;
    }
    stos.PB({nei, w});
    Dfs(nei);
    stos.pop_back();
  }
}
const int MOD = 1e9 + 7;
const int INV2 = (MOD + 1) / 2;
const int N = 1 << 20;
// Transforms the interval [x, y) in a.
void transform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  transform(x, z, a);
  transform(z, y, a);
  for (int i=x; i<z; i++) {
    int x1 = a[i];
    int x2 = a[i+l2];
    a[i] = (x1 - x2 + MOD) % MOD;
    a[i+l2] = (x1 + x2) % MOD;
  }
}
// Reverses the transform in
// the interval [x, y) in a.
void untransform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  for (int i=x; i<z; i++) {
    long long y1 = a[i];
    long long y2 = a[i+l2];
    // x1 - x2 = y1
    // x1 + x2 = y2
    // 2 * x1  = y1 + y2
    // 2 * x2  = y2 - y1

    // In order to solve those equations, we need to divide by 2
    // But we are performing operations modulo 1000000007
    // that needs us to find the modular multiplicative inverse of 2.
    // That is saved in the INV2 variable.

    a[i] = (int)( ((y1 + y2)*INV2) % MOD );
    a[i+l2] = (int)( ((y2 - y1 + MOD)*INV2) % MOD );
  }
  untransform(x, z, a);
  untransform(z, y, a);
}

VI Mnoz(VI A, VI B) {
  transform(0, M, &A[0]);
  transform(0, M, &B[0]);
  REP (i, M) {
    A[i] = A[i] * B[i] % MOD;
  }
  untransform(0, M, &A[0]);
  return A;
}

int32_t main() {

  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin.tie(0);
  //double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;

  int n, m;
  cin>>n>>m;
  int xorr = 0;
  RE (i, m) {
    int a, b, w;
    cin>>a>>b>>w;
    xorr ^= w;
    slo[a].PB({b, w});
    slo[b].PB({a, w});
  }
  stos.PB({1, 0});
  Dfs(1);
  debug(cycles);
  VI cur(M);
  cur[0] = 1;
  for (auto cycle : cycles) {
    VI cyc_cnt(M);
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    cur = Mnoz(cur, cyc_cnt);
  }
  int min_res = 1e9;
  int wh_min = -1;
  REP (i, M) {
    if (cur[i]) {
      int cand_xor = xorr ^ i;
      if (cand_xor < min_res) {
        min_res = cand_xor;
        wh_min = i;
      }
    }
  }
  cout<<min_res<<" "<<cur[wh_min]<<"\n";

  return 0;
}


#include <bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define st first
#define nd second
#define rd third
#define FOR(i, a, b) for(int i =(a); i <=(b); ++i)
#define RE(i, n) FOR(i, 1, n)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define REP(i, n) for(int i = 0;i <(n); ++i)
#define VAR(v, i) __typeof(i) v=(i)
#define FORE(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define __builtin_ctz __builtin_ctzll
#define __builtin_clz __builtin_clzll
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<typename TH> void _dbg(const char* sdbg, TH h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename TH, typename... TA> void _dbg(const char* sdbg, TH h, TA... t) {
  while(*sdbg != ',') { cerr<<*sdbg++; } cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}
#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(itt, (x)) cerr <<*itt <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define cerr if(0)cout
#endif
#define next ____next
#define prev ____prev
#define left ____left
#define hash ____hash
typedef long long ll;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VLL;
typedef vector<pair<int, int> > VPII;
typedef vector<pair<ll, ll> > VPLL;

template<class C> void mini(C&a4, C b4){a4=min(a4, b4); }
template<class C> void maxi(C&a4, C b4){a4=max(a4, b4); }
template<class T1, class T2>
ostream& operator<< (ostream &out, pair<T1, T2> pair) { return out << "(" << pair.first << ", " << pair.second << ")";}
template<class A, class B, class C> struct Triple { A first; B second; C third;
  bool operator<(const Triple& t) const { if (st != t.st) return st < t.st; if (nd != t.nd) return nd < t.nd; return rd < t.rd; } };
template<class T> void ResizeVec(T&, vector<int>) {}
template<class T> void ResizeVec(vector<T>& vec, vector<int> sz) {
  vec.resize(sz[0]); sz.erase(sz.begin()); if (sz.empty()) { return; }
  for (T& v : vec) { ResizeVec(v, sz); }
}
typedef Triple<int, int, int> TIII;
template<class A, class B, class C>
ostream& operator<< (ostream &out, Triple<A, B, C> t) { return out << "(" << t.st << ", " << t.nd << ", " << t.rd << ")"; }
template<class T> ostream& operator<<(ostream& out, vector<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class T> ostream& operator<<(ostream& out, set<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class L, class R> ostream& operator<<(ostream& out, map<L, R> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }

const int M = 1 << 17;
VVI cycles;
VPII stos;
VPII slo[M];
int vis[M];
int d;
int pre[M];
void Dfs(int v) {
  vis[v] = 1;
  pre[v] = d++;
  for (auto e : slo[v]) {
    int nei = e.st;
    int w = e.nd;
    if (vis[nei]) {
      if (SZ(stos) >= 2 && stos[SZ(stos) - 2].st == nei) { continue; }
      if (pre[nei] > pre[v]) { continue; }
      debug(nei, v);
      cycles.PB(VI{w});
      FORD (ind, SZ(stos) - 1, 0){
        if (stos[ind].st == nei) { break; }
        cycles.back().PB(stos[ind].nd);
      }
      continue;
    }
    stos.PB({nei, w});
    Dfs(nei);
    stos.pop_back();
  }
}
int MOD = 1e9 + 7;
const int M2 = 999999197;
const int INV2 = (MOD + 1) / 2;
void SelfMod(int& a) {
  while (a >= MOD) {
    a -= MOD;
  }
}
void Dziel(int& a) {
  if (a % 2 == 0) {
    a /= 2;
  } else {
    a = (a + MOD) / 2;
  }
}
//const int N = 1 << 20;
// Transforms the interval [x, y) in a.
void transform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  transform(x, z, a);
  transform(z, y, a);
  for (int i=x; i<z; i++) {
    int x1 = a[i];
    int x2 = a[i+l2];
    a[i] = (x1 - x2 + MOD);
    a[i+l2] = (x1 + x2);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
  }
}
// Reverses the transform in
// the interval [x, y) in a.
void untransform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  for (int i=x; i<z; i++) {
    long long y1 = a[i];
    long long y2 = a[i+l2];
    // x1 - x2 = y1
    // x1 + x2 = y2
    // 2 * x1  = y1 + y2
    // 2 * x2  = y2 - y1

    // In order to solve those equations, we need to divide by 2
    // But we are performing operations modulo 1000000007
    // that needs us to find the modular multiplicative inverse of 2.
    // That is saved in the INV2 variable.

    a[i] = (y1 + y2);
    a[i+l2] = (y2 - y1 + MOD);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
    Dziel(a[i]);
    Dziel(a[i + l2]);
  }
  untransform(x, z, a);
  untransform(z, y, a);
}

// void Mnoz(VI& A, VI& B) {
//   transform(0, M, &A[0]);
//   transform(0, M, &B[0]);
//   REP (i, M) {
//     A[i] = (long long) A[i] * B[i] % MOD;
//   }
//   untransform(0, M, &A[0]);
//   //return A;
// }

int32_t main() {

  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin.tie(0);
  //double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;

  int n, m;
  cin>>n>>m;
  int xorr = 0;
  RE (i, m) {
    int a, b, w;
    cin>>a>>b>>w;
    xorr ^= w;
    slo[a].PB({b, w});
    slo[b].PB({a, w});
  }
  stos.PB({1, 0});
  Dfs(1);
  debug(cycles);
  VI cur(M), cur2(M);
  cur[0] = 1;
  transform(0, M, &cur[0]);
  MOD = M2;
  cur2[0] = 1;
  transform(0, M, &cur2[0]);
  for (auto cycle : cycles) {
    VI cyc_cnt(M);
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = 1e9 + 7;
    transform(0, M, &cyc_cnt[0]);
    REP (i, M) {
      cur[i] = 1ll * cur[i] * cyc_cnt[i] % MOD;
    }
    REP (i, M) {
      cyc_cnt[i] = 0;
    }
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = M2;
    transform(0, M, &cyc_cnt[0]);
    REP (i, M) {
      cur2[i] = 1ll * cur2[i] * cyc_cnt[i] % MOD;
    }
    //Mnoz(cur, cyc_cnt);
//     MOD = M2;
//     cur2 = Mnoz(cur2, cyc_cnt);
  }
  int min_res = 1e9;
  int wh_min = -1;
  MOD = 1e9 + 7;
  untransform(0, M, &cur[0]);
  MOD = M2;
  untransform(0, M, &cur2[0]);
  if (n < 45) {
    assert(cur == cur2);
  }
  REP (i, M) {
    if (cur[i] && cur2[i]) {
      int cand_xor = xorr ^ i;
      if (cand_xor < min_res) {
        min_res = cand_xor;
        wh_min = i;
      }
    }
  }
  cout<<min_res<<" "<<cur[wh_min]<<"\n";

  return 0;
}


#include <bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define st first
#define nd second
#define rd third
#define FOR(i, a, b) for(int i =(a); i <=(b); ++i)
#define RE(i, n) FOR(i, 1, n)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define REP(i, n) for(int i = 0;i <(n); ++i)
#define VAR(v, i) __typeof(i) v=(i)
#define FORE(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define __builtin_ctz __builtin_ctzll
#define __builtin_clz __builtin_clzll
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<typename TH> void _dbg(const char* sdbg, TH h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename TH, typename... TA> void _dbg(const char* sdbg, TH h, TA... t) {
  while(*sdbg != ',') { cerr<<*sdbg++; } cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}
#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(itt, (x)) cerr <<*itt <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define cerr if(0)cout
#endif
#define next ____next
#define prev ____prev
#define left ____left
#define hash ____hash
typedef long long ll;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VLL;
typedef vector<pair<int, int> > VPII;
typedef vector<pair<ll, ll> > VPLL;

template<class C> void mini(C&a4, C b4){a4=min(a4, b4); }
template<class C> void maxi(C&a4, C b4){a4=max(a4, b4); }
template<class T1, class T2>
ostream& operator<< (ostream &out, pair<T1, T2> pair) { return out << "(" << pair.first << ", " << pair.second << ")";}
template<class A, class B, class C> struct Triple { A first; B second; C third;
  bool operator<(const Triple& t) const { if (st != t.st) return st < t.st; if (nd != t.nd) return nd < t.nd; return rd < t.rd; } };
template<class T> void ResizeVec(T&, vector<int>) {}
template<class T> void ResizeVec(vector<T>& vec, vector<int> sz) {
  vec.resize(sz[0]); sz.erase(sz.begin()); if (sz.empty()) { return; }
  for (T& v : vec) { ResizeVec(v, sz); }
}
typedef Triple<int, int, int> TIII;
template<class A, class B, class C>
ostream& operator<< (ostream &out, Triple<A, B, C> t) { return out << "(" << t.st << ", " << t.nd << ", " << t.rd << ")"; }
template<class T> ostream& operator<<(ostream& out, vector<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class T> ostream& operator<<(ostream& out, set<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class L, class R> ostream& operator<<(ostream& out, map<L, R> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }

const int M = 1 << 17;
VVI cycles;
VPII stos;
VPII slo[M];
int vis[M];
int d;
int pre[M];
void Dfs(int v) {
  vis[v] = 1;
  pre[v] = d++;
  for (auto e : slo[v]) {
    int nei = e.st;
    int w = e.nd;
    if (vis[nei]) {
      if (SZ(stos) >= 2 && stos[SZ(stos) - 2].st == nei) { continue; }
      if (pre[nei] > pre[v]) { continue; }
      debug(nei, v);
      cycles.PB(VI{w});
      FORD (ind, SZ(stos) - 1, 0){
        if (stos[ind].st == nei) { break; }
        cycles.back().PB(stos[ind].nd);
      }
      continue;
    }
    stos.PB({nei, w});
    Dfs(nei);
    stos.pop_back();
  }
}
int MOD = 1e9 + 7;
const int INV2 = (MOD + 1) / 2;
void SelfMod(int& a) {
  while (a >= MOD) {
    a -= MOD;
  }
}
void Dziel(int& a) {
  if (a % 2 == 0) {
    a /= 2;
  } else {
    a = (a + MOD) / 2;
  }
}
//const int N = 1 << 20;
// Transforms the interval [x, y) in a.
void transform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  transform(x, z, a);
  transform(z, y, a);
  for (int i=x; i<z; i++) {
    int x1 = a[i];
    int x2 = a[i+l2];
    a[i] = (x1 - x2 + MOD);
    a[i+l2] = (x1 + x2);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
  }
}
// Reverses the transform in
// the interval [x, y) in a.
void untransform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  for (int i=x; i<z; i++) {
    long long y1 = a[i];
    long long y2 = a[i+l2];
    // x1 - x2 = y1
    // x1 + x2 = y2
    // 2 * x1  = y1 + y2
    // 2 * x2  = y2 - y1

    // In order to solve those equations, we need to divide by 2
    // But we are performing operations modulo 1000000007
    // that needs us to find the modular multiplicative inverse of 2.
    // That is saved in the INV2 variable.

    a[i] = (y1 + y2);
    a[i+l2] = (y2 - y1 + MOD);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
    Dziel(a[i]);
    Dziel(a[i + l2]);
  }
  untransform(x, z, a);
  untransform(z, y, a);
}

VI Mnoz(VI A, VI B) {
  transform(0, M, &A[0]);
  transform(0, M, &B[0]);
  REP (i, M) {
    A[i] = (long long) A[i] * B[i] % MOD;
  }
  untransform(0, M, &A[0]);
  return A;
}

int32_t main() {

  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin.tie(0);
  //double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;

  int n, m;
  cin>>n>>m;
  int xorr = 0;
  RE (i, m) {
    int a, b, w;
    cin>>a>>b>>w;
    xorr ^= w;
    slo[a].PB({b, w});
    slo[b].PB({a, w});
  }
  stos.PB({1, 0});
  Dfs(1);
  debug(cycles);
  VI cur(M), cur2(M);
  cur[0] = 1;
  cur2[0] = 1;
  for (auto cycle : cycles) {
    VI cyc_cnt(M);
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = 1e9 + 7;
    cur = Mnoz(cur, cyc_cnt);
    MOD = 1e9 + 9;
    cur2 = Mnoz(cur2, cyc_cnt);
  }
  int min_res = 1e9;
  int wh_min = -1;
  REP (i, M) {
    if (cur[i] && cur2[i]) {
      int cand_xor = xorr ^ i;
      if (cand_xor < min_res) {
        min_res = cand_xor;
        wh_min = i;
      }
    }
  }
  cout<<min_res<<" "<<cur[wh_min]<<"\n";

  return 0;
}


#include <bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define st first
#define nd second
#define rd third
#define FOR(i, a, b) for(int i =(a); i <=(b); ++i)
#define RE(i, n) FOR(i, 1, n)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define REP(i, n) for(int i = 0;i <(n); ++i)
#define VAR(v, i) __typeof(i) v=(i)
#define FORE(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define __builtin_ctz __builtin_ctzll
#define __builtin_clz __builtin_clzll
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<typename TH> void _dbg(const char* sdbg, TH h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename TH, typename... TA> void _dbg(const char* sdbg, TH h, TA... t) {
  while(*sdbg != ',') { cerr<<*sdbg++; } cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}
#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(itt, (x)) cerr <<*itt <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define cerr if(0)cout
#endif
#define next ____next
#define prev ____prev
#define left ____left
#define hash ____hash
typedef long long ll;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VLL;
typedef vector<pair<int, int> > VPII;
typedef vector<pair<ll, ll> > VPLL;

template<class C> void mini(C&a4, C b4){a4=min(a4, b4); }
template<class C> void maxi(C&a4, C b4){a4=max(a4, b4); }
template<class T1, class T2>
ostream& operator<< (ostream &out, pair<T1, T2> pair) { return out << "(" << pair.first << ", " << pair.second << ")";}
template<class A, class B, class C> struct Triple { A first; B second; C third;
  bool operator<(const Triple& t) const { if (st != t.st) return st < t.st; if (nd != t.nd) return nd < t.nd; return rd < t.rd; } };
template<class T> void ResizeVec(T&, vector<int>) {}
template<class T> void ResizeVec(vector<T>& vec, vector<int> sz) {
  vec.resize(sz[0]); sz.erase(sz.begin()); if (sz.empty()) { return; }
  for (T& v : vec) { ResizeVec(v, sz); }
}
typedef Triple<int, int, int> TIII;
template<class A, class B, class C>
ostream& operator<< (ostream &out, Triple<A, B, C> t) { return out << "(" << t.st << ", " << t.nd << ", " << t.rd << ")"; }
template<class T> ostream& operator<<(ostream& out, vector<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class T> ostream& operator<<(ostream& out, set<T> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }
template<class L, class R> ostream& operator<<(ostream& out, map<L, R> vec) { out<<"("; for (auto& v: vec) out<<v<<", "; return out<<")"; }

const int M = 1 << 17;
VVI cycles;
VPII stos;
VPII slo[M];
int vis[M];
int d;
int pre[M];
void Dfs(int v) {
  vis[v] = 1;
  pre[v] = d++;
  for (auto e : slo[v]) {
    int nei = e.st;
    int w = e.nd;
    if (vis[nei]) {
      if (SZ(stos) >= 2 && stos[SZ(stos) - 2].st == nei) { continue; }
      if (pre[nei] > pre[v]) { continue; }
      debug(nei, v);
      cycles.PB(VI{w});
      FORD (ind, SZ(stos) - 1, 0){
        if (stos[ind].st == nei) { break; }
        cycles.back().PB(stos[ind].nd);
      }
      continue;
    }
    stos.PB({nei, w});
    Dfs(nei);
    stos.pop_back();
  }
}
int MOD = 1e9 + 7;
const int INV2 = (MOD + 1) / 2;
void SelfMod(int& a) {
  while (a >= MOD) {
    a -= MOD;
  }
}
void Dziel(int& a) {
  if (a % 2 == 0) {
    a /= 2;
  } else {
    a = (a + MOD) / 2;
  }
}
//const int N = 1 << 20;
// Transforms the interval [x, y) in a.
void transform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  transform(x, z, a);
  transform(z, y, a);
  for (int i=x; i<z; i++) {
    int x1 = a[i];
    int x2 = a[i+l2];
    a[i] = (x1 - x2 + MOD);
    a[i+l2] = (x1 + x2);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
  }
}
// Reverses the transform in
// the interval [x, y) in a.
void untransform(int x, int y, int* a)
{
  if ( x == y - 1) {
    return;
  }
  int l2 = ( y - x ) / 2;
  int z = x + l2;
  for (int i=x; i<z; i++) {
    long long y1 = a[i];
    long long y2 = a[i+l2];
    // x1 - x2 = y1
    // x1 + x2 = y2
    // 2 * x1  = y1 + y2
    // 2 * x2  = y2 - y1

    // In order to solve those equations, we need to divide by 2
    // But we are performing operations modulo 1000000007
    // that needs us to find the modular multiplicative inverse of 2.
    // That is saved in the INV2 variable.

    a[i] = (y1 + y2);
    a[i+l2] = (y2 - y1 + MOD);
    SelfMod(a[i]);
    SelfMod(a[i + l2]);
    Dziel(a[i]);
    Dziel(a[i + l2]);
  }
  untransform(x, z, a);
  untransform(z, y, a);
}

// void Mnoz(VI& A, VI& B) {
//   transform(0, M, &A[0]);
//   transform(0, M, &B[0]);
//   REP (i, M) {
//     A[i] = (long long) A[i] * B[i] % MOD;
//   }
//   untransform(0, M, &A[0]);
//   //return A;
// }

int32_t main() {

  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin.tie(0);
  //double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;

  int n, m;
  cin>>n>>m;
  int xorr = 0;
  RE (i, m) {
    int a, b, w;
    cin>>a>>b>>w;
    xorr ^= w;
    slo[a].PB({b, w});
    slo[b].PB({a, w});
  }
  stos.PB({1, 0});
  Dfs(1);
  debug(cycles);
  VI cur(M), cur2(M);
  cur[0] = 1;
  transform(0, M, &cur[0]);
  MOD = 1e9 + 9;
  cur2[0] = 1;
  transform(0, M, &cur2[0]);
  for (auto cycle : cycles) {
    VI cyc_cnt(M);
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = 1e9 + 7;
    transform(0, M, &cyc_cnt[0]);
    REP (i, M) {
      cur[i] = 1ll * cur[i] * cyc_cnt[i] % MOD;
    }
    REP (i, M) {
      cyc_cnt[i] = 0;
    }
    for (auto x : cycle) {
      cyc_cnt[x]++;
    }
    MOD = 1e9 + 9;
    transform(0, M, &cyc_cnt[0]);
    REP (i, M) {
      cur2[i] = 1ll * cur2[i] * cyc_cnt[i] % MOD;
    }
    //Mnoz(cur, cyc_cnt);
//     MOD = 1e9 + 9;
//     cur2 = Mnoz(cur2, cyc_cnt);
  }
  int min_res = 1e9;
  int wh_min = -1;
  MOD = 1e9 + 7;
  untransform(0, M, &cur[0]);
  MOD = 1e9 + 9;
  untransform(0, M, &cur2[0]);
  REP (i, M) {
    if (cur[i] && cur2[i]) {
      int cand_xor = xorr ^ i;
      if (cand_xor < min_res) {
        min_res = cand_xor;
        wh_min = i;
      }
    }
  }
  cout<<min_res<<" "<<cur[wh_min]<<"\n";

  return 0;
}


// #pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <list>

// hloya template v25

// ░░░░░░░▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▄░░░░░░
// ░░░░░░█░░▄▀▀▀▀▀▀▀▀▀▀▀▀▀▄░░█░░░░░
// ░░░░░░█░█░▀░░░░░▀░░▀░░░░█░█░░░░░
// ░░░░░░█░█░░░░░░░░▄▀▀▄░▀░█░█▄▀▀▄░
// █▀▀█▄░█░█░░▀░░░░░█░░░▀▄▄█▄▀░░░█░
// ▀▄▄░▀██░█▄░▀░░░▄▄▀░░░░░░░░░░░░▀▄
// ░░▀█▄▄█░█░░░░▄░░█░░░▄█░░░▄░▄█░░█
// ░░░░░▀█░▀▄▀░░░░░█░██░▄░░▄░░▄░███
// ░░░░░▄█▄░░▀▀▀▀▀▀▀▀▄░░▀▀▀▀▀▀▀░▄▀░
// ░░░░█░░▄█▀█▀▀█▀▀▀▀▀▀█▀▀█▀█▀▀█░░░
// ░░░░▀▀▀▀░░▀▀▀░░░░░░░░▀▀▀░░▀▀░░░░

#include <bits/stdc++.h>
#include <valarray>
using namespace std;

clock_t start_time = clock();
#define current_time fixed<<setprecision(6)<<(ld)(clock()-start_time)/CLOCKS_PER_SEC

#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()

#define ll long long
#define ld long double
#define pii pair<int,int>
#define umap unordered_map<int, int>

#define files1 freopen("input.txt","r",stdin)
#define files2 freopen("output.txt","w",stdout)
#define files files1;files2
#define fast_io ios_base::sync_with_stdio(0);cin.tie(0)

// #define endl '\n'
#define ln(i,n) " \n"[(i) == (n) - 1]

void bad(string mes = "Impossible"){cout << mes;exit(0);}
void bad(int mes){cout << mes;exit(0);}

template<typename T>
string bin(T x, int st = 2){
    string ans = "";
    while (x > 0){
        ans += char('0' + x % st);
        x /= st;
    }
    reverse(ans.begin(), ans.end());
    return ans.empty() ? "0" : ans;
}

template<typename T>
void upmax(T& x, T y) {
    x = max(x, y);
}

template<typename T>
void upmin(T& x, T y) {
    x = min(x, y);
}

// inline int popcount(int x){
//     int count = 0;
//     __asm__ volatile("POPCNT %1, %0;":"=r"(count):"r"(x):);
//     return count;
// }

template<typename T>
T input(){
    T ans = 0, m = 1;
    char c = ' ';

    while (!((c >= '0' && c <= '9') || c == '-')) {
        c = getchar();
    }

    if (c == '-')
        m = -1, c = getchar();
    while (c >= '0' && c <= '9'){
        ans = ans * 10 + (c - '0'), c = getchar();
    }
    return ans * m;
}

template<typename T> void read(T& a) { a = input<T>(); }
template<typename T> void read(T& a, T& b) { read(a), read(b); }
template<typename T> void read(T& a, T& b, T& c) { read(a, b), read(c); }
template<typename T> void read(T& a, T& b, T& c, T& d) { read(a, b), read(c, d); }

const int inf = 1e9 + 20;
const short short_inf = 3e4 + 20;
const long double eps = 1e-6;
const int maxn = (int)2e5 + 12;//, base = 1e9 + 7;
const ll llinf = 2e18 + 5;
const double PI = acos(-1.0);

const int mod = 1e9 + 7;

template<typename T>
T binpow(T n, T s)
{
    if (s <= 0)
        return 1LL;
    if (s % 2 == 0){
        T b = binpow(n, s / 2);
        return ( 1LL * b * b ) % mod;
    } else {
        return (1LL* binpow(n, s - 1) * n) % mod;
    }
}

vector<int> tmp;
int used[200000];
vector<vector<int>> kek;

vector<int> st;
vector<pii> g[maxn];
map<pii, int> sot;

int getEdge(int u, int v) {
    return sot[minmax(u, v)];
}

void dfs(int v, int p = -1) {
    used[v] = 2;
    st.pb(v);

    for (auto [to, w] : g[v]) {
        if (to == p) continue;

        if (used[to] == 2) {
            tmp.clear();
            for (int i = st.size() - 1; st[i] != to; i--) {
                tmp.pb(getEdge(st[i], st[i - 1]));
            }
            tmp.pb(w);
            kek.pb(tmp);
        } else if (used[to] == 0) {
            dfs(to, v);
        }
    }

    st.pop_back();
    used[v] = 1;
}

int poly[45][140000];
int ans[140000];

void transform(int id, int from, int to) //int *from, int *to)
{
    if(to - from == 1)
        return;
    int mid = from + (to - from) / 2;
    transform(id, from, mid);
    transform(id, mid, to);
    for(int i = 0; i < mid - from; i++)
    {
        int a = poly[id][from + i];
        int b = poly[id][mid + i];//*(mid + i);
        poly[id][from + i] = (a + b) % mod;
        poly[id][mid + i] = (a - b + mod) % mod;
    }
}

int inv(int x) {
    return binpow(x, mod - 2);
}

int main() {
    fast_io;
    // files1;

    int n, m;
    cin >> n >> m;

    int x = 0;

    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        g[u].pb({v, w});
        g[v].pb({u, w});
        sot[minmax(u,v)] = w;
        x ^= w;
    }

    for (int i = 0; i < n; i++) if (!used[i]) dfs(i);

    assert(kek.size() < 43);

    if (kek.size() == 0) {
        cout << x << ' ' << 1 << endl;
        return 0;
    }

    for (int i = 0; i < kek.size(); i++) {
        for (int j : kek[i]) {
            poly[i][j]++;
        }
        transform(i, 0, (1 << 17));
        // for (int j = 0; j ) {

        // }
        for (int j = 0; j < (1 << 17); j++) {
            if (i == 0) poly[43][j] = poly[i][j];
            else {
                poly[43][j] = 1ll * poly[43][j] * poly[i][j] % mod;
            }
        }
    }

    transform(43, 0, (1 << 17));
    int re = mod, mda;

    for (int i = 0; i < (1 << 17); i++) {
        if (poly[43][i]) {
            poly[43][i] = 1ll * poly[43][i] * inv(1 << 17) % mod;
            if ((i ^ x) < re) {
                re = i ^ x;
                mda = poly[43][i];
            }
        }
    }
    cout << re << ' ' << mda;
    return 0;
}


// #pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <list>

// hloya template v25

// ░░░░░░░▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▄░░░░░░
// ░░░░░░█░░▄▀▀▀▀▀▀▀▀▀▀▀▀▀▄░░█░░░░░
// ░░░░░░█░█░▀░░░░░▀░░▀░░░░█░█░░░░░
// ░░░░░░█░█░░░░░░░░▄▀▀▄░▀░█░█▄▀▀▄░
// █▀▀█▄░█░█░░▀░░░░░█░░░▀▄▄█▄▀░░░█░
// ▀▄▄░▀██░█▄░▀░░░▄▄▀░░░░░░░░░░░░▀▄
// ░░▀█▄▄█░█░░░░▄░░█░░░▄█░░░▄░▄█░░█
// ░░░░░▀█░▀▄▀░░░░░█░██░▄░░▄░░▄░███
// ░░░░░▄█▄░░▀▀▀▀▀▀▀▀▄░░▀▀▀▀▀▀▀░▄▀░
// ░░░░█░░▄█▀█▀▀█▀▀▀▀▀▀█▀▀█▀█▀▀█░░░
// ░░░░▀▀▀▀░░▀▀▀░░░░░░░░▀▀▀░░▀▀░░░░

#include <bits/stdc++.h>
#include <valarray>
using namespace std;

clock_t start_time = clock();
#define current_time fixed<<setprecision(6)<<(ld)(clock()-start_time)/CLOCKS_PER_SEC

#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()

#define ll long long
#define ld long double
#define pii pair<int,int>
#define umap unordered_map<int, int>

#define files1 freopen("input.txt","r",stdin)
#define files2 freopen("output.txt","w",stdout)
#define files files1;files2
#define fast_io ios_base::sync_with_stdio(0);cin.tie(0)

// #define endl '\n'
#define ln(i,n) " \n"[(i) == (n) - 1]

void bad(string mes = "Impossible"){cout << mes;exit(0);}
void bad(int mes){cout << mes;exit(0);}

template<typename T>
string bin(T x, int st = 2){
    string ans = "";
    while (x > 0){
        ans += char('0' + x % st);
        x /= st;
    }
    reverse(ans.begin(), ans.end());
    return ans.empty() ? "0" : ans;
}

template<typename T>
void upmax(T& x, T y) {
    x = max(x, y);
}

template<typename T>
void upmin(T& x, T y) {
    x = min(x, y);
}

// inline int popcount(int x){
//     int count = 0;
//     __asm__ volatile("POPCNT %1, %0;":"=r"(count):"r"(x):);
//     return count;
// }

template<typename T>
T input(){
    T ans = 0, m = 1;
    char c = ' ';

    while (!((c >= '0' && c <= '9') || c == '-')) {
        c = getchar();
    }

    if (c == '-')
        m = -1, c = getchar();
    while (c >= '0' && c <= '9'){
        ans = ans * 10 + (c - '0'), c = getchar();
    }
    return ans * m;
}

template<typename T> void read(T& a) { a = input<T>(); }
template<typename T> void read(T& a, T& b) { read(a), read(b); }
template<typename T> void read(T& a, T& b, T& c) { read(a, b), read(c); }
template<typename T> void read(T& a, T& b, T& c, T& d) { read(a, b), read(c, d); }

const int inf = 1e9 + 20;
const short short_inf = 3e4 + 20;
const long double eps = 1e-6;
const int maxn = (int)2e5 + 12;//, base = 1e9 + 7;
const ll llinf = 2e18 + 5;
const double PI = acos(-1.0);

const int mod = 1e9 + 7;
const int mod2 = 1e9 + 9;

template<typename T>
T binpow(T n, T s)
{
    if (s <= 0)
        return 1LL;
    if (s % 2 == 0){
        T b = binpow(n, s / 2);
        return ( 1LL * b * b ) % mod;
    } else {
        return (1LL* binpow(n, s - 1) * n) % mod;
    }
}

vector<int> tmp;
int used[200000];
vector<vector<int>> kek;

vector<int> st;
vector<pii> g[maxn];
map<pii, int> sot;

int getEdge(int u, int v) {
    return sot[minmax(u, v)];
}

void dfs(int v, int p = -1) {
    used[v] = 2;
    st.pb(v);

    for (auto [to, w] : g[v]) {
        if (to == p) continue;

        if (used[to] == 2) {
            tmp.clear();
            for (int i = st.size() - 1; st[i] != to; i--) {
                tmp.pb(getEdge(st[i], st[i - 1]));
            }
            tmp.pb(w);
            kek.pb(tmp);
        } else if (used[to] == 0) {
            dfs(to, v);
        }
    }

    st.pop_back();
    used[v] = 1;
}

int poly[45][140000];
int poly2[45][140000];

void transform(int id, int from, int to)
{
    if(to - from == 1)
        return;
    int mid = from + (to - from) / 2;
    transform(id, from, mid);
    transform(id, mid, to);
    for(int i = 0; i < mid - from; i++)
    {
        int a = poly[id][from + i];
        int b = poly[id][mid + i];
        poly[id][from + i] = (a + b) % mod;
        poly[id][mid + i] = ((a - b) % mod + mod) % mod;

        a = poly2[id][from + i];
        b = poly2[id][mid + i];
        poly2[id][from + i] = (a + b) % mod2;
        poly2[id][mid + i] = ((a - b) % mod2 + mod2) % mod2;
    }
}

int inv(int x) {
    return binpow(x, mod - 2);
}

int main() {
    fast_io;
    // files1;

    int n, m;
    cin >> n >> m;

    int x = 0;

    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        u--, v--;
        g[u].pb({v, w});
        g[v].pb({u, w});
        sot[minmax(u,v)] = w;
        x ^= w;
    }

    for (int i = 0; i < n; i++) if (!used[i]) dfs(i);

    assert(kek.size() < 43);

    if (kek.size() == 0) {
        cout << x << ' ' << 1 << endl;
        return 0;
    }

    for (int i = 0; i < kek.size(); i++) {
        for (int j : kek[i]) {
            poly[i][j]++;
            poly2[i][j]++;
        }
        transform(i, 0, (1 << 17));

        for (int j = 0; j < (1 << 17); j++) {
            if (i == 0) poly[43][j] = poly[i][j];
            else {
                poly[43][j] = 1ll * poly[43][j] * poly[i][j] % mod;
            }
        }
        for (int j = 0; j < (1 << 17); j++) {
            if (i == 0) poly2[43][j] = poly2[i][j];
            else {
                poly2[43][j] = 1ll * poly2[43][j] * poly2[i][j] % mod2;
            }
        }
    }

    transform(43, 0, (1 << 17));
    int re = mod, mda;

    for (int i = 0; i < (1 << 17); i++) {
        if (poly[43][i] || poly2[43][i]) {
            poly[43][i] = 1ll * poly[43][i] * inv(1 << 17) % mod;

            if ((i ^ x) < re) {
                re = i ^ x;
                mda = poly[43][i];
            }
        }
    }
    cout << re << ' ' << mda;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<vector>
const int N=1e5+5,M=44;
typedef long long ll;
const int mod=1e9+7,inv2=(mod+1)/2;
void FWT(int *a,int n,bool inv=0) {
    int x,y;
    for(int i=1;i<n;i<<=1)
        for(int p=i<<1,j=0;j<n;j+=p)
            for(int k=0;k<i;k++) {
                x=a[j+k];y=a[i+j+k];
                a[j+k]=(x+y)%mod;a[i+j+k]=(x+mod-y)%mod;
                if(inv) a[j+k]=1LL*a[j+k]*inv2%mod,a[i+j+k]=1LL*a[i+j+k]*inv2%mod;
            }
}
std::vector<int> g[N];
std::vector<int> bcc[N],val[N];
struct Edge {
    int u,v,w;
    void input() {
        scanf("%d%d%d",&u,&v,&w);
    }
}e[N+M];
int dfn[N],low[N],stk[N],top,tot,cnt,n,m,blg[N];
void tarjan(int u,int fa) {
    dfn[u]=low[u]=++tot;stk[top++]=u;
    for(int v:g[u]) if(v!=fa) {
        if(!dfn[v]) tarjan(v,u),low[u]=std::min(low[v],low[u]);
        else low[u]=std::min(low[u],dfn[v]);
    }
    if(low[u]!=dfn[u]) return;
    ++cnt;
    while(1) {
        int v=stk[--top];
        blg[v]=cnt;
        bcc[cnt].push_back(v);
        if(v==u) break;
    }
}
int f[N<<2],h[N<<2];
int main() {
    scanf("%d%d",&n,&m);
    int mx=0;
    for(int i=1;i<=m;i++) {
        e[i].input();
        g[e[i].u].push_back(e[i].v);
        g[e[i].v].push_back(e[i].u);
        mx=std::max(mx,e[i].w);
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,i);
    int ans=0;
    int len=1;
    while(len<=mx) len<<=1;
    for(int i=1,u,v;i<=m;i++) {
        u=e[i].u;
        v=e[i].v;
        if(blg[u]!=blg[v]) ans^=e[i].w;
        else val[blg[u]].push_back(e[i].w);
    }
    f[ans]=1;
    for(int i=1;i<=cnt;i++) if(val[i].size()>1) {
        for(int j=0;j<len;j++) h[j]=0;
        int t=0;
        for(int v:val[i]) t^=v;
        for(int v:val[i]) h[t^v]=1;
        FWT(h,len);FWT(f,len);
        for(int j=0;j<len;j++) f[j]=1LL*f[j]*h[j]%mod;
        FWT(f,len,1);
        for(int j=0;j<len;j++) if(f[j]>0) f[j]=1;
    }
    int res=len;
    for(int j=0;j<len;j++) if(f[j]) {
        res=j;
        break;
    }
    for(int j=0;j<len;j++) f[j]=0;
    f[ans]++;
    FWT(f,len);
    for(int i=1;i<=cnt;i++) if(val[i].size()>1) {
        for(int j=0;j<len;j++) h[j]=0;
        int t=0;
        for(int v:val[i]) t^=v;
        for(int v:val[i]) h[t^v]++;
        FWT(h,len);
        for(int j=0;j<len;j++) f[j]=1LL*f[j]*h[j]%mod;
    }
    FWT(f,len,1);
    printf("%d %d\n",res,f[res]);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<vector>
const int N=1e5+5,M=44;
typedef long long ll;
const ll mod=1e9+7,inv2=(mod+1)/2;
void FWT(ll *a,int n,bool inv=0) {
    int x,y;
    for(int i=1;i<n;i<<=1)
        for(int p=i<<1,j=0;j<n;j+=p)
            for(int k=0;k<i;k++) {
                x=a[j+k];y=a[i+j+k];
                a[j+k]=(x+y)%mod;a[i+j+k]=(x+mod-y)%mod;
                if(inv) a[j+k]=a[j+k]*inv2%mod,a[i+j+k]=a[i+j+k]*inv2%mod;
            }
}
std::vector<int> g[N];
std::vector<int> bcc[N],val[N];
struct Edge {
    int u,v,w;
    void input() {
        scanf("%d%d%d",&u,&v,&w);
    }
}e[N+M];
int dfn[N],low[N],stk[N],top,tot,cnt,n,m,blg[N];
void tarjan(int u,int fa) {
    dfn[u]=low[u]=++tot;stk[top++]=u;
    for(int v:g[u]) {
        if(!dfn[v]) tarjan(v,u),low[u]=std::min(low[v],low[u]);
        else low[u]=std::min(low[u],dfn[v]);
    }
    if(low[u]!=dfn[u]) return;
    ++cnt;
    while(1) {
        int v=stk[--top];
        blg[v]=cnt;
        bcc[cnt].push_back(v);
        if(v==u) break;
    }
}
ll f[N<<2],h[N<<2];
int main() {
    scanf("%d%d",&n,&m);
    int mx=0;
    for(int i=1;i<=m;i++) {
        e[i].input();
        g[e[i].u].push_back(e[i].v);
        g[e[i].v].push_back(e[i].u);
        mx=std::max(mx,e[i].w);
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,i);
    int ans=0;
    int len=1;
    while(len<=mx) len<<=1;
    for(int i=1,u,v;i<=m;i++) {
        u=e[i].u;
        v=e[i].v;
        if(blg[u]!=blg[v]) ans^=e[i].w;
        else val[blg[u]].push_back(e[i].w);
    }
    f[ans]=1;
    for(int i=1;i<=cnt;i++) if(val[i].size()>1) {
        for(int j=0;j<len;j++) h[j]=0;
        int t=0;
        for(int v:val[i]) t^=v;
        for(int v:val[i]) h[t^v]=1;
        h[t]=1;
        FWT(h,len);FWT(f,len);
        for(int j=0;j<len;j++) f[j]=f[j]*h[j]%mod;
        FWT(f,len,1);
        for(int j=0;j<len;j++) if(f[j]>0) f[j]=1;
    }
    int res=len;
    for(int j=0;j<len;j++) if(f[j]) {
        res=j;
        break;
    }
    for(int j=0;j<len;j++) f[j]=0;
    f[ans]++;
    FWT(f,len);
    for(int i=1;i<=cnt;i++) if(val[i].size()>1) {
        for(int j=0;j<len;j++) h[j]=0;
        int t=0;
        for(int v:val[i]) t^=v;
        h[t]++;
        for(int v:val[i]) h[t^v]++;
        FWT(h,len);
        for(int j=0;j<len;j++) f[j]=f[j]*h[j]%mod;
    }
    FWT(f,len,1);
    printf("%d %lld\n",res,f[res]);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<vector>
const int N=1e5+5,M=44;
typedef long long ll;
const ll mod=1e9+7,inv2=(mod+1)/2;
void FWT(ll *a,int n,bool inv=0) {
    int x,y;
    for(int i=1;i<n;i<<=1)
        for(int p=i<<1,j=0;j<n;j+=p)
            for(int k=0;k<i;k++) {
                x=a[j+k];y=a[i+j+k];
                a[j+k]=(x+y)%mod;a[i+j+k]=(x+mod-y)%mod;
                if(inv) a[j+k]=a[j+k]*inv2%mod,a[i+j+k]=a[i+j+k]*inv2%mod;
            }
}
std::vector<int> g[N];
std::vector<int> bcc[N],val[N];
struct Edge {
    int u,v,w;
    void input() {
        scanf("%d%d%d",&u,&v,&w);
    }
}e[N+M];
int dfn[N],low[N],stk[N],top,tot,cnt,n,m,blg[N];
void tarjan(int u,int fa) {
    dfn[u]=low[u]=++tot;stk[top++]=u;
    for(int v:g[u]) {
        if(!dfn[v]) tarjan(v,u),low[u]=std::min(low[v],low[u]);
        else low[u]=std::min(low[u],dfn[v]);
    }
    if(low[u]!=dfn[u]) return;
    ++cnt;
    while(1) {
        int v=stk[--top];
        blg[v]=cnt;
        bcc[cnt].push_back(v);
        if(v==u) break;
    }
}
ll f[N<<2],h[N<<2];
int main() {
    scanf("%d%d",&n,&m);
    int mx=0;
    for(int i=1;i<=m;i++) {
        e[i].input();
        g[e[i].u].push_back(e[i].v);
        g[e[i].v].push_back(e[i].u);
        mx=std::max(mx,e[i].w);
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,i);
    int ans=0;
    int len=1;
    while(len<=mx) len<<=1;
    for(int i=1,u,v;i<=m;i++) {
        u=e[i].u;
        v=e[i].v;
        if(blg[u]!=blg[v]) ans^=e[i].w;
        else val[blg[u]].push_back(e[i].w);
    }
    f[ans]=1;
    for(int i=1;i<=cnt;i++) if(val[i].size()>1) {
        for(int j=0;j<len;j++) h[j]=0;
        int t=0;
        for(int v:val[i]) t^=v;
        for(int v:val[i]) h[t^v]=1;
        FWT(h,len);FWT(f,len);
        for(int j=0;j<len;j++) f[j]=f[j]*h[j]%mod;
        FWT(f,len,1);
        for(int j=0;j<len;j++) if(f[j]>0) f[j]=1;
    }
    int res=len;
    for(int j=0;j<len;j++) if(f[j]) {
        res=j;
        break;
    }
    for(int j=0;j<len;j++) f[j]=0;
    f[ans]++;
    FWT(f,len);
    for(int i=1;i<=cnt;i++) if(val[i].size()>1) {
        for(int j=0;j<len;j++) h[j]=0;
        int t=0;
        for(int v:val[i]) t^=v;
        for(int v:val[i]) h[t^v]++;
        FWT(h,len);
        for(int j=0;j<len;j++) f[j]=f[j]*h[j]%mod;
    }
    FWT(f,len,1);
    printf("%d %lld\n",res,f[res]);
    return 0;
}