#include <cstdio>
#include <cassert>
#include <algorithm>
#include <chrono>
#include <unordered_set>
#include <cstring>
#include <vector>
using namespace std;

struct custom_hash {
	static uint64_t splitmix64(uint64_t x) {
		x += 0x9e3779b97f4a7c15;
		x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
		x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
		return x ^ (x >> 31);
	}
	size_t operator()(uint64_t x) const {
		static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
		return splitmix64(x + FIXED_RANDOM);
	}
};

const int N = 200000;
const int LG = 30;
int n;
int a[N];

int t[N * LG][2];
int sz[N * LG];
int ends[N * LG];
struct trie {
	trie() {}
	trie(int *a, int n) {
		int cnt = 1;
		for (int i = 0; i < n; ++i) {
			int v = 0;
			for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
				int b = (bool)(a[i] & bit);
				if (t[v][b]) v = t[v][b];
				else v = t[v][b] = cnt++;
				++sz[v];
			}
			ends[v] = i;
		}
	}
	void insert(int a) {
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			v = t[v][(bool)(a & bit)];
			++sz[v];
		}
	}
	void erase(int a) {
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			v = t[v][(bool)(a & bit)];
			--sz[v];
		}
	}
	pair<pair<int, long long>, int> min(int a, int i) {
		int len = 0;
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			int b = (bool)(a & bit);
			if (sz[t[v][b]] > 0) {
				v = t[v][b];
			}
			else {
				len |= bit;
				v = t[v][b ^ 1];
			}
		}
		return make_pair(make_pair(len, (long long)std::min(ends[v], i) * N + std::max(ends[v], i)), ends[v]);
	}
};

vector<int> g[N];
vector<vector<int> > comp;
int no[N];
trie tr;

bool u[N];
void dfs(int v, vector<int> &compv)
{
	u[v] = true;
	compv.push_back(v);
	for (int i = 0; i < g[v].size(); ++i) if (!u[g[v][i]]) dfs(g[v][i], compv);
}

long long mst()
{
	comp.resize(n);
	for (int i = 0; i < n; ++i) comp[i].push_back(i);
	long long cost = 0;
	int op = 0;
	while (comp.size() > 1) {
		++op;
		assert(op <= 50);
		vector<pair<pair<int, int>, int> > add_edge;
		for (int i = 0; i < comp.size(); ++i) {
			for (int j = 0; j < comp[i].size(); ++j)
				tr.erase(a[comp[i][j]]);
			pair<pair<int, long long>, int> res(make_pair(~(1 << 31), (long long)0), 0);
			int from;
			for (int j = 0; j < comp[i].size(); ++j) {
				pair<pair<int, long long>, int> t = tr.min(a[comp[i][j]], comp[i][j]);
				if (res > t) {
					res = t;
					from = comp[i][j];
				}
			}
			add_edge.push_back(make_pair(make_pair(min(from, res.second), max(from, res.second)), res.first.first));
			for (int j = 0; j < comp[i].size(); ++j)
				tr.insert(a[comp[i][j]]);
		}
		sort(add_edge.begin(), add_edge.end());
		for (int i = 0; i < add_edge.size(); ++i) {
			if (!i || add_edge[i].first != add_edge[i - 1].first) {
				g[add_edge[i].first.first].push_back(add_edge[i].first.second);
				g[add_edge[i].first.second].push_back(add_edge[i].first.first);
				cost += add_edge[i].second;
			}
		}
		memset(u, 0, sizeof(*u) * n);
		comp.clear();
		for (int i = 0; i < n; ++i) if (!u[i]) {
			comp.push_back(vector<int>());
			dfs(i, comp.back());
		}
	}
	return cost;
}

unordered_set<int> distinct;

int main()
{
	scanf("%d", &n);
	int v;
	for (int i = 0; i < n; ++i) {
		scanf("%d", &v);
		distinct.insert(v);
	}
	n = 0;
	for (int i : distinct) a[n++] = i;
	tr = trie(a, n);
	printf("%lld\n", mst());
	return 0;
}


#include <cstdio>
#include <algorithm>
#include <chrono>
#include <unordered_set>
#include <cstring>
#include <vector>
using namespace std;

struct dsu {
	dsu *p;
	int size;
	dsu() {
		p = this;
		size = 1;
	}
	dsu *find();
};
dsu *dsu::find() {
	if (p == this) return this;
	return p = p->find();
}
bool same(dsu *a, dsu *b)
{
	return a->find() == b->find();
}
void unite(dsu *a, dsu *b)
{
	a = a->find();
	b = b->find();
	if (a->size < b->size) swap(a, b);
	a->size += b->size;
	b->p = a;
}

struct custom_hash {
	static uint64_t splitmix64(uint64_t x) {
		x += 0x9e3779b97f4a7c15;
		x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
		x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
		return x ^ (x >> 31);
	}
	size_t operator()(uint64_t x) const {
		static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
		return splitmix64(x + FIXED_RANDOM);
	}
};

const int N = 200000;
const int LG = 30;
int n;
int a[N];

int t[N * LG][2];
int sz[N * LG];
int ends[N * LG];
struct trie {
	trie() {}
	trie(int *a, int n) {
		int cnt = 1;
		for (int i = 0; i < n; ++i) {
			int v = 0;
			for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
				int b = (bool)(a[i] & bit);
				if (t[v][b]) v = t[v][b];
				else v = t[v][b] = cnt++;
				++sz[v];
			}
			ends[v] = i;
		}
	}
	void insert(int a) {
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			v = t[v][(bool)(a & bit)];
			++sz[v];
		}
	}
	void erase(int a) {
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			v = t[v][(bool)(a & bit)];
			--sz[v];
		}
	}
	pair<int, int> min(int a) {
		int len = 0;
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			int b = (bool)(a & bit);
			if (sz[t[v][b]] > 0) {
				v = t[v][b];
			}
			else {
				len |= bit;
				v = t[v][b ^ 1];
			}
		}
		return make_pair(len, ends[v]);
	}
};

vector<int> g[N];
vector<vector<int> > comp;
dsu ds[N];
trie tr;

bool u[N];
void dfs(int v, vector<int> &compv)
{
	u[v] = true;
	compv.push_back(v);
	for (int i = 0; i < g[v].size(); ++i) if (!u[g[v][i]]) dfs(g[v][i], compv);
}

long long mst()
{
	comp.resize(n);
	for (int i = 0; i < n; ++i) comp[i].push_back(i);
	long long cost = 0;
	int any = comp.size();
	while (any > 1) {
		vector<pair<pair<int, int>, int> > add_edge;
		for (int i = 0; i < comp.size(); ++i) if (comp[i].size()) {
			for (int j = 0; j < comp[i].size(); ++j)
				tr.erase(a[comp[i][j]]);
			pair<int, int> res(~(1 << 31), 0);
			int from;
			for (int j = 0; j < comp[i].size(); ++j) {
				pair<int, int> t = tr.min(a[comp[i][j]]);
				if (res.first > t.first) {
					res = t;
					from = comp[i][j];
				}
			}
			if (!same(ds + from, ds + res.second)) {
				g[from].push_back(res.second);
				g[res.second].push_back(from);
				unite(ds + from, ds + res.second);
				cost += res.first;
			}
			for (int j = 0; j < comp[i].size(); ++j)
				tr.insert(a[comp[i][j]]);
		}
		memset(u, 0, sizeof(*u) * n);
		comp.clear();
		comp.resize(n);
		any = 0;
		for (int i = 0; i < n; ++i) {
			if (comp[ds[i].find() - ds].empty()) ++any;
			comp[ds[i].find() - ds].push_back(i);
		}
	}
	return cost;
}

unordered_set<int> distinct;

int main()
{
	scanf("%d", &n);
	int v;
	for (int i = 0; i < n; ++i) {
		scanf("%d", &v);
		distinct.insert(v);
	}
	n = 0;
	for (int i : distinct) a[n++] = i;
	tr = trie(a, n);
	printf("%lld\n", mst());
	return 0;
}


#include <cstdio>
#include <algorithm>
#include <chrono>
#include <cassert>
#include <unordered_set>
#include <set>
#include <cstring>
#include <vector>
using namespace std;

struct custom_hash {
	static uint64_t splitmix64(uint64_t x) {
		x += 0x9e3779b97f4a7c15;
		x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
		x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
		return x ^ (x >> 31);
	}
	size_t operator()(uint64_t x) const {
		static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
		return splitmix64(x + FIXED_RANDOM);
	}
};

const int N = 200000;
const int LG = 30;
int n;
int a[N];

int t[N * LG][2];
int sz[N * LG];
int ends[N * LG];
struct trie {
	trie() {}
	trie(int *a, int n) {
		int cnt = 1;
		for (int i = 0; i < n; ++i) {
			int v = 0;
			for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
				int b = (bool)(a[i] & bit);
				if (t[v][b]) v = t[v][b];
				else v = t[v][b] = cnt++;
				++sz[v];
			}
			ends[v] = i;
		}
	}
	void insert(int a) {
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			v = t[v][(bool)(a & bit)];
			++sz[v];
		}
	}
	void erase(int a) {
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			v = t[v][(bool)(a & bit)];
			--sz[v];
		}
	}
	pair<int, int> min(int a) {
		int len = 0;
		int v = 0;
		for (int bit = 1 << (LG - 1); bit; bit >>= 1) {
			int b = (bool)(a & bit);
			if (sz[t[v][b]] > 0) {
				v = t[v][b];
			}
			else {
				len |= bit;
				v = t[v][b ^ 1];
			}
		}
		return make_pair(len, ends[v]);
	}
};

vector<int> g[N];
vector<vector<int> > comp;
trie tr;

bool u[N];
void dfs(int v, vector<int> &compv)
{
	u[v] = true;
	compv.push_back(v);
	for (int i = 0; i < g[v].size(); ++i) if (!u[g[v][i]]) dfs(g[v][i], compv);
}

long long mst()
{
	comp.resize(n);
	for (int i = 0; i < n; ++i) comp[i].push_back(i);
	long long cost = 0;
	while (comp.size() > 1) {
		vector<pair<pair<int, int>, int> > add_edge;
		for (int i = 0; i < comp.size(); ++i) {
			for (int j = 0; j < comp[i].size(); ++j)
				tr.erase(a[comp[i][j]]);
			pair<int, int> res(~(1 << 31), 0);
			int from;
			for (int j = 0; j < comp[i].size(); ++j) {
				pair<int, int> t = tr.min(a[comp[i][j]]);
				if (res > t) {
					res = t;
					from = comp[i][j];
				}
			}
			add_edge.push_back(make_pair(make_pair(min(from, res.second), max(from, res.second)), res.first));
			for (int j = 0; j < comp[i].size(); ++j)
				tr.insert(a[comp[i][j]]);
		}
		sort(add_edge.begin(), add_edge.end());
		for (int i = 0; i < add_edge.size(); ++i) {
			if (!i || add_edge[i].first != add_edge[i - 1].first) {
				g[add_edge[i].first.first].push_back(add_edge[i].first.second);
				g[add_edge[i].first.second].push_back(add_edge[i].first.first);
				cost += add_edge[i].second;
			}
		}
		memset(u, 0, sizeof(*u) * n);
		comp.clear();
		for (int i = 0; i < n; ++i) if (!u[i]) {
			comp.push_back(vector<int>());
			dfs(i, comp.back());
		}
	}
	return cost;
}

set<int> distinct;

int main()
{
	scanf("%d", &n);
	int v;
	for (int i = 0; i < n; ++i) {
		scanf("%d", &v);
		distinct.insert(v);
	}
	n = 0;
	for (int i : distinct) a[n++] = i;
	tr = trie(a, n);
	printf("%lld\n", mst());
	return 0;
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5 + 1000;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = !dir;
		curr = lr[dir][curr];
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5 + 5e4;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = !dir;
		curr = lr[dir][curr];
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5 + 1000;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = dir ^ 1;
		curr = lr[dir][curr];
		if (curr == -1) return -1;
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					if (nm == -1) continue;
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				if (mn.second < INF) {
					unite(x, mn.second);
					nowS--;
					ans += mn.first;
				}
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5 + 1000;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = !dir;
		//if (curr == -1) while (true);
		curr = lr[dir][curr];
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5 + 1000;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = !dir;
		if (curr == -1) while (true);
		curr = lr[dir][curr];
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5 + 1000;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = !dir;
		curr = lr[dir][curr];
		if (curr == -1) while (true);
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = !dir;
		curr = lr[dir][curr];
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5 + 1000;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = !dir;
		curr = lr[dir][curr];
		if (curr == -1) return -1;
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					if (nm == -1) continue;
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 3e5;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir = !dir;
		curr = lr[dir][curr];
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}
				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define eb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define int long long

using namespace std;
const int INF = 1e15;
const int MB = 30;
const int MOD = 1e9 + 7;
const int maxN = 2e5 + 1000;

int lr[2][maxN * MB], cnt[maxN * MB], num[maxN * MB], p[maxN];
vector<int> comp[maxN];

int find(int x) {
	if (x == p[x]) return x;
	return p[x] = find(p[x]);
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);

	if (comp[a].size() < comp[b].size()) swap(a, b);
	for (int i : comp[b]) comp[a].push_back(i);
	p[b] = a;
}

int now = 1;

void insert(int x, int id) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1) lr[dir][curr] = now++;
		curr = lr[dir][curr];
		cnt[curr]++;
	}
	num[curr] = id;
}

void del(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		curr = lr[dir][curr];
		cnt[curr]--;
	}
}

int get(int x) {
	int curr = 0;
	for (int i = MB - 1; i >= 0; i--) {
		int dir = (x >> i) & 1;
		if (lr[dir][curr] == -1 || !cnt[lr[dir][curr]]) dir ^= 1;
		curr = lr[dir][curr];
	}
	return num[curr];
}

void solve() {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	sort(all(a));
	a.erase(unique(all(a)), a.end());
	n = a.size();

	for (int i = 0; i < MB * maxN; i++) {
		lr[0][i] = lr[1][i] = -1;
	}

	for (int i = 0; i < n; i++) {
		insert(a[i], i);
		p[i] = i;
		comp[i] = { i };
	}

	int q = 1;
	vector<int> used(n);
	int nowS = n;
	int ans = 0;

	while (nowS > 1) {
		for (int i = 0; i < n && nowS > 1; i++) {
			if (used[find(i)] != q) {
				used[find(i)] = q;
				int x = find(i);
				for (int j : comp[x]) {
					del(a[j]);
				}
				pair<int, int> mn = { INF, INF };
				for (int j : comp[x]) {
					int nm = get(a[j]);
					mn = min(mn, { a[j] ^ a[nm], nm });
				}
				for (int j : comp[x]) {
					insert(a[j], j);
				}

				unite(x, mn.second);
				nowS--;
				ans += mn.first;
			}
		}
		q++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed;
	cout.precision(12);
	srand(time(0));
	int t = 1;
	//int t;
	//cin >> t;
	while (t--) solve();
}


//I/O
#include<iostream>
#include<sstream>
//Containers
#include<deque>
#include<initializer_list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<string>
#include<unordered_map>
#include<unordered_set>
#include<vector>
//C library
#include<cmath>
#include<cassert>
#include<cctype>
#include<climits>
#include<cmath>
#include<cstddef>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
//Miscellaneous
#include<algorithm>
#include<bitset>
#include<complex>
#include<functional>
#include<iomanip>
#include<iterator>
#include<limits>
#include<numeric>
#include<random>
#include<tuple>
#include<utility>

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>

#define en '\n'
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define repi(i, a, b) for(int i=(a); i>(b); i--)
#define db(x) (cerr << #x << ": " << (x) << '\n')
#define sync ios_base::sync_with_stdio(false), cin.tie(NULL)
#define tests(t) int t; cin >> t; while(t--)
#define iceil(n, x) (((n) + (x) - 1) / (x))
#define ll long long
#define gcd __gcd
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define sz size()
#define all(v) (v).begin(), (v).end()
#define uni(v) sort(all(v)); (v).erase(unique(all(v)), (v).end());
#define pii pair<int, int>
#define vi vector<int>
#define vpii vector<pii>
#define vvi vector<vi>
#define fi first
#define se second
#define umap unordered_map
#define uset unordered_set
#define pqueue priority_queue
#define si(a) scanf("%d", &a)
#define sll(a) scanf("%lld", &a)
#define bitcount(x) __builtin_popcount(x)
#define cps CLOCKS_PER_SEC
#define PI acos(-1.0)
#define EPS 1e-9
#define mod 1000000007
using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cerr << name << " : " << arg1 << '\n';
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
using maxpq = priority_queue<T>;

//All indexing is 0-based
//using namespace __gnu_pbds;
//typedef tree<int, null_type, less<int>, rb_tree_tag,
             //tree_order_statistics_node_update> ordered_set;
//methods: find_by_order(k); & order_of_key(k);
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

template<typename T>
void printv(const vector<T>& v) { for(auto i : v) cerr << i << ' '; cerr << '\n'; }

//Returns no. of values x for which ceil(n / x) == y (y must be > 1).
inline ll CC(ll n, ll y) { return iceil(n, y-1) - iceil(n, y); }

//Returns no. of values x for which floor(n / x) == y
inline ll FF(ll n, ll y) { return n / y - n / (y+1); }

inline ll gcd(ll a, ll b) { return !b ? a: gcd(b, a%b); }

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c;}
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c;}
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p;}

#define N 200005
//#define int ll
//#define trace(...) 42

//SZ[i]: size of the set that the ith element is a root of

//Only valid for root elements

int par[N], Rank[N], SZ[N];

int num_sets;

int n; //number of vertices

//Rank[x] is an upper bound to the height

//of the subtree roted at node x.

void make_set(int x)

{

	num_sets++;

	par[x]=x;

	Rank[x]=0;

	SZ[x] = 1;

}

void init() {

	num_sets = 0;

	for(int i = 0; i < n; i++) make_set(i);

}

//returns the representative of the set

//to which x belongs.

int find_set(int x)

{

	if(par[x]==x)

		return x;

	else

		return par[x]=find_set(par[x]);

}

//Returns the size of set that the ith vertex is in

int sizeofSet(int i) {

	return SZ[find_set(i)];

}

bool merge_sets(int x,int y)

{

	int rx=find_set(x),ry=find_set(y);

	if(rx==ry)

		return 0;

	else{

		num_sets--;

		if(Rank[rx]==Rank[ry])// Anyone can be the others' parent

			par[ry]=rx,Rank[rx]++, SZ[rx]+= SZ[ry];

		else if(Rank[rx]<Rank[ry])

			par[rx]=ry, SZ[ry]+= SZ[rx];

		else

			par[ry]=rx, SZ[rx]+=SZ[ry];

			return 1;
	}

}

struct trienode {

    bool eow = 0;

    int idx;
    int cnt = 0;

    trienode* ar[2] = {NULL, NULL};

};

inline bool bit(int x, int b) {

    return (x >> b) & 1;

}

struct Trie {

    const int bits = 32; //# bits in the number

    trienode* root = new trienode;

    void insert(int x, int idx) {

        trienode* curr = root;

        for(int i = bits-1; i >= 0; i--) {

            int b = bit(x, i);

            if(curr -> ar[b] == NULL)

                curr -> ar[b] = new trienode;

            curr = curr -> ar[b];

            curr -> cnt++;

        }

        curr -> eow = 1;

        curr -> idx = idx;
    }

    int query(int x) {

        trienode* curr = root;

        int ans = 0;

        for(int i = bits-1; i >= 0; i--) {

            if(!curr) return ans;

            int bx = bit(x, i);

            if(curr -> ar[bx])
                     curr = curr -> ar[bx];
             else
                    curr = curr -> ar[!bx];

        }

        return curr -> idx;

    }

    void erase(int x) {

        trienode* curr = root;

        for(int i = bits-1; i >= 0; i--) {

            int b = bit(x, i);

            (curr -> ar[b] -> cnt)--;

            if(curr -> ar[b] -> cnt == 0) {

                curr -> ar[b] = NULL;

                return;

            }

            curr = curr -> ar[b];

        }

    }

};

vi adj[N];
int a[N], ans;

int32_t main()
{
    #ifndef ONLINE_JUDGE
        freopen("/storage/emulated/0/input.txt", "r", stdin);
    //freopen("/storage/emulated/0/output.txt", "w", stdout);
    #endif
    sync;
    clock_t clk = clock();
    cerr << "I will return...\n";

    cin >> n;
    rep(i, 0, n) cin >> a[i];

    sort(a, a + n);
    n = unique(a, a + n) - a;

    init();
    Trie T;

    rep(i, 0, n) T.insert(a[i], i);

    while(num_sets > 1) {
        fill_n(adj, n, vi());
        rep(i, 0, n) adj[find_set(i)].pb(i);

        rep(i, 0, n) {
            if(adj[i].empty()) continue;
            for(int j : adj[i]) T.erase(a[j]);
            int mnw;
            pii mnp;
            mnw = 2e9;

            for (int j : adj[i]) {
                int k = T.query(a[j]);
                int x = a[j] ^ a[k];
                if(x < mnw) {
                    mnw = x;
                    mnp = {j, k};
                }
            }
            int x, y; tie(x, y) = mnp;
            if(merge_sets(x, y)) ans += a[x] ^ a[y];

            for(int j : adj[i]) T.insert(a[j], j);
        }
    }

    cout << ans << en;

    cerr << "...don't you ever hang your head.\n";
    cerr << "Time (in ms): " << double(clock() - clk) * 1000.0 / cps << '\n';
}

//Compile using:
//g++ -o filename.exe --std=c++11 filename.cpp
//Use -D CP for defining a macro CP in the local environment


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define repi(i, a, b) for(int i=(a); i>(b); i--)
#define db(x) (cerr << #x << ": " << (x) << '\n')
#define sync ios_base::sync_with_stdio(false), cin.tie(NULL)
#define tests(t) int t; cin >> t; while(t--)
#define iceil(n, x) (((n) + (x) - 1) / (x))
#define ll long long
#define gcd __gcd
#define eb emplace_back
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define sz size()
#define all(v) (v).begin(), (v).end()
#define uni(v) sort(all(v)); (v).erase(unique(all(v)), (v).end())
#define pii pair<int, int>
#define vi vector<int>
#define vpii vector<pii>
#define vvi vector<vi>
#define fi first
#define se second
#define pqueue priority_queue
#define bitcount(x) __builtin_popcount(x)
#define cps CLOCKS_PER_SEC
#define PI acos(-1.0)
#define EPS 1e-9
#define mod 1000000007
using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cerr << name << " : " << arg1 << '\n';
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}

template<typename T1, typename T2>
ostream& operator << (ostream& os, const pair<T1, T2>& p) { return os << '(' << p.fi << ", " << p.se << ')'; }

template<typename T>
void printv(const T& v) { for(auto i : v) cerr << i << ' '; cerr << '\n'; }

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
using maxpq = priority_queue<T>;

//All indexing is 0-based
using namespace __gnu_pbds;
template<class key, class cmp = std::less<key>>
using ordered_set = tree<key, null_type, cmp, rb_tree_tag, tree_order_statistics_node_update>;
//methods: find_by_order(k); & order_of_key(k);
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar

template<class key, class value, class cmp = std::less<key>>
using ordered_map = tree<key, value, cmp, rb_tree_tag, tree_order_statistics_node_update>;

//Returns no. of values x for which ceil(n / x) == y (y must be > 1).
inline ll CC(ll n, ll y) { return iceil(n, y-1) - iceil(n, y); }

//Returns no. of values x for which floor(n / x) == y
inline ll FF(ll n, ll y) { return n / y - n / (y+1); }

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

#define N 200005
// #define int ll
// #define trace(...) 42

struct trienode {
    bool eow = 0;
    int cnt = 0;
    trienode* ar[2] = {NULL, NULL};
};

inline bool bit(int x, int b) {
    return (x >> b) & 1;
}

//Uses an improved version of erase() to prevent memory leak
//Rather than deleting nodes make the cnt = 0
struct Trie {
    const int bits = 32; //# bits in the number
    trienode* root = new trienode;

    void insert(int x) {
        trienode* curr = root;
        curr -> cnt++;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            if(curr -> ar[b] == NULL)
                curr -> ar[b] = new trienode;
            curr = curr -> ar[b];
            curr -> cnt++;
        }
        curr -> eow = 1;
    }

    //Returns the smallest xor value that can be obtained
    //on xoring x with some no. already present in the Trie.
    int query(int x) {
        int ans = 0;
        trienode* curr = root;
        for(int i = bits-1; i >= 0; i--) {
            int bx = bit(x, i);
            if(curr -> ar[bx] && curr -> ar[bx] -> cnt) curr = curr -> ar[bx];
            else curr = curr -> ar[!bx], ans |= 1 << i;
        }
        return ans;
    }

    void erase(int x) {
        trienode* curr = root;
        curr -> cnt--;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            (curr -> ar[b] -> cnt)--;
            curr = curr -> ar[b];
        }
    }
};

int n, a[N];
ll ans;
Trie T;

//Construct an MST for the elements in the range [l, r)
void solve(int l, int r, int b) {
    if(r - l <= 0 || b < 0) return;

    int p = l;
    while(p < r && bit(a[p], b) == 0) ++p;

    if(p == l || p == r) return solve(l, r, b-1);

    //Split the range [l, r) into [l, p) and [p, r)
    //Build the MST for the 2 small ranges
    solve(l, p, b-1);
    solve(p, r, b-1);

    rep(i, l, p) T.insert(a[i]);

    int mn = 2e9;
    rep(i, p, r) mn = min(mn, T.query(a[i]));
    ans += mn;
    //mn is the min. weight edge joining the 2 MSTs.

    rep(i, l, p) T.erase(a[i]);
}

main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/tarun/Desktop/input.txt", "r", stdin);
     // freopen("/home/tarun/Desktop/output.txt", "w", stdout);
    #endif
    sync;
    clock_t clk = clock();
    cerr << "I will return...\n";

    cin >> n;
    rep(i, 0, n) cin >> a[i];
    sort(a, a + n);

    solve(0, n, 30);

    cout << ans << '\n';

    cerr << "...don't you ever hang your head.\n";
    cerr << "Time (in ms): " << (double)(clock() - clk) * 1000.0 / cps << '\n';
}

//Compile using:
//g++ -o filename.exe --std=c++11 filename.cpp
//Use -D CP for defining a macro CP in the local environment


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define repi(i, a, b) for(int i=(a); i>(b); i--)
#define db(x) (cerr << #x << ": " << (x) << '\n')
#define sync ios_base::sync_with_stdio(false), cin.tie(NULL)
#define tests(t) int t; cin >> t; while(t--)
#define iceil(n, x) (((n) + (x) - 1) / (x))
#define ll long long
#define gcd __gcd
#define eb emplace_back
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define sz size()
#define all(v) (v).begin(), (v).end()
#define uni(v) sort(all(v)); (v).erase(unique(all(v)), (v).end())
#define pii pair<int, int>
#define vi vector<int>
#define vpii vector<pii>
#define vvi vector<vi>
#define fi first
#define se second
#define pqueue priority_queue
#define bitcount(x) __builtin_popcount(x)
#define cps CLOCKS_PER_SEC
#define PI acos(-1.0)
#define EPS 1e-9
#define mod 1000000007
using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cerr << name << " : " << arg1 << '\n';
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}

template<typename T1, typename T2>
ostream& operator << (ostream& os, const pair<T1, T2>& p) { return os << '(' << p.fi << ", " << p.se << ')'; }

template<typename T>
void printv(const T& v) { for(auto i : v) cerr << i << ' '; cerr << '\n'; }

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
using maxpq = priority_queue<T>;

//All indexing is 0-based
using namespace __gnu_pbds;
template<class key, class cmp = std::less<key>>
using ordered_set = tree<key, null_type, cmp, rb_tree_tag, tree_order_statistics_node_update>;
//methods: find_by_order(k); & order_of_key(k);
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar

template<class key, class value, class cmp = std::less<key>>
using ordered_map = tree<key, value, cmp, rb_tree_tag, tree_order_statistics_node_update>;

//Returns no. of values x for which ceil(n / x) == y (y must be > 1).
inline ll CC(ll n, ll y) { return iceil(n, y-1) - iceil(n, y); }

//Returns no. of values x for which floor(n / x) == y
inline ll FF(ll n, ll y) { return n / y - n / (y+1); }

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

#define N 200005
// #define int ll
// #define trace(...) 42

//SZ[i]: size of the set that the ith element is a root of
//Only valid for root elements
int par[N], Rank[N], SZ[N];
int num_sets;
int n; //number of vertices
//Rank[x] is an upper bound to the height
//of the subtree roted at node x.
void make_set(int x)
{
    num_sets++;
    par[x]=x;
    Rank[x]=0;
    SZ[x] = 1;
}

void init() {
    num_sets = 0;
    for(int i = 0; i < n; i++) make_set(i);
}

//returns the representative of the set
//to which x belongs.
int find_set(int x)
{

    if(par[x]==x)
        return x;
    else
        return par[x]=find_set(par[x]);
}

//Returns the size of set that the ith vertex is in
int sizeofSet(int i) {
    return SZ[find_set(i)];
}

bool merge_sets(int x,int y)
{
    int rx=find_set(x),ry=find_set(y);
    if(rx==ry)
        return 0;
    else{
        num_sets--;
        if(Rank[rx]==Rank[ry])// Anyone can be the others' parent
            par[ry]=rx,Rank[rx]++, SZ[rx]+= SZ[ry];
        else if(Rank[rx]<Rank[ry])
            par[rx]=ry, SZ[ry]+= SZ[rx];
        else
            par[ry]=rx, SZ[rx]+=SZ[ry];
            return 1;
    }
}

struct trienode {
    int idx;
    int cnt;
    int ar[2];
    trienode(int _idx = 0)
        :idx(_idx), cnt(0), ar{NULL, NULL}{}
};

//0th node is the NULL node
int num = 1;
trienode node[30*N];

inline bool bit(int x, int b) {
    return (x >> b) & 1;
}

struct Trie {
    const int bits = 32; //# bits in the number
    int root = num++;
    void insert(int x, int idx) {
        int curr = root;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            if(node[curr].ar[b] == NULL)
                node[curr].ar[b] = num++;
            curr = node[curr].ar[b];
            node[curr].cnt++;
        }
        node[curr].idx = idx;
    }

    int query(int x) {
        int curr = root;
        int ans = 0;
        for(int i = bits-1; i >= 0; i--) {
            int bx = bit(x, i);
            if(node[node[curr].ar[bx]].cnt)
                curr = node[curr].ar[bx], ans |= bx << i;
            else
                curr = node[curr].ar[!bx], ans |= !bx << i;
        }
        // trace(x, ans, node[curr].idx);
        return node[curr].idx;
    }

    void erase(int x) {
        int curr = root;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            node[node[curr].ar[b]].cnt--;
            if(node[node[curr].ar[b]].cnt == 0) {
                // node[curr].ar[b] = NULL;
                return;
            }
            curr = node[curr].ar[b];
        }
    }
};

vi adj[N];
int a[N];
ll ans;

main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/tarun/Desktop/input.txt", "r", stdin);
     // freopen("/home/tarun/Desktop/output.txt", "w", stdout);
    #endif
    sync;
    clock_t clk = clock();
    cerr << "I will return...\n";

    cin >> n;
    rep(i, 0, n) cin >> a[i];

    // trace(n);
    // rep(i, 0, n) trace(i, a[i]);

    sort(a, a + n);
    n = unique(a, a + n) - a;

    init();
    Trie T;

    rep(i, 0, n) T.insert(a[i], i);

    while(num_sets > 1) {
        rep(i, 0, n) adj[i].clear();
        rep(i, 0, n) adj[find_set(i)].pb(i);

        rep(i, 0, n) {
            if(adj[i].empty()) continue;
            for(int j : adj[i]) {
                // trace(j, a[j], T.query(a[j]));
                T.erase(a[j]);
            }
            int mnw;
            pii mnp;
            mnw = 2e9;

            for (int j : adj[i]) {
                int k = T.query(a[j]);
                int x = a[j] ^ a[k];
                if(x < mnw) {
                    mnw = x;
                    mnp = {j, k};
                }
            }
            int x, y; tie(x, y) = mnp;
            if(merge_sets(x, y)) ans += a[x] ^ a[y];

            for(int j : adj[i]) T.insert(a[j], j);
        }
    }

    cout << ans << '\n';

    cerr << "...don't you ever hang your head.\n";
    cerr << "Time (in ms): " << (double)(clock() - clk) * 1000.0 / cps << '\n';
}

//Compile using:
//g++ -o filename.exe --std=c++11 filename.cpp
//Use -D CP for defining a macro CP in the local environment


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define repi(i, a, b) for(int i=(a); i>(b); i--)
#define db(x) (cerr << #x << ": " << (x) << '\n')
#define sync ios_base::sync_with_stdio(false), cin.tie(NULL)
#define tests(t) int t; cin >> t; while(t--)
#define iceil(n, x) (((n) + (x) - 1) / (x))
#define ll long long
#define gcd __gcd
#define eb emplace_back
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define sz size()
#define all(v) (v).begin(), (v).end()
#define uni(v) sort(all(v)); (v).erase(unique(all(v)), (v).end())
#define pii pair<int, int>
#define vi vector<int>
#define vpii vector<pii>
#define vvi vector<vi>
#define fi first
#define se second
#define pqueue priority_queue
#define bitcount(x) __builtin_popcount(x)
#define cps CLOCKS_PER_SEC
#define PI acos(-1.0)
#define EPS 1e-9
#define mod 1000000007
using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cerr << name << " : " << arg1 << '\n';
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}

template<typename T1, typename T2>
ostream& operator << (ostream& os, const pair<T1, T2>& p) { return os << '(' << p.fi << ", " << p.se << ')'; }

template<typename T>
void printv(const T& v) { for(auto i : v) cerr << i << ' '; cerr << '\n'; }

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
using maxpq = priority_queue<T>;

//All indexing is 0-based
using namespace __gnu_pbds;
template<class key, class cmp = std::less<key>>
using ordered_set = tree<key, null_type, cmp, rb_tree_tag, tree_order_statistics_node_update>;
//methods: find_by_order(k); & order_of_key(k);
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar

template<class key, class value, class cmp = std::less<key>>
using ordered_map = tree<key, value, cmp, rb_tree_tag, tree_order_statistics_node_update>;

//Returns no. of values x for which ceil(n / x) == y (y must be > 1).
inline ll CC(ll n, ll y) { return iceil(n, y-1) - iceil(n, y); }

//Returns no. of values x for which floor(n / x) == y
inline ll FF(ll n, ll y) { return n / y - n / (y+1); }

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

#define N 200005
// #define int ll
// #define trace(...) 42

//SZ[i]: size of the set that the ith element is a root of
//Only valid for root elements
int par[N], Rank[N], SZ[N];
int num_sets;
int n; //number of vertices
//Rank[x] is an upper bound to the height
//of the subtree roted at node x.
void make_set(int x)
{
    num_sets++;
    par[x]=x;
    Rank[x]=0;
    SZ[x] = 1;
}

void init() {
    num_sets = 0;
    for(int i = 0; i < n; i++) make_set(i);
}

//returns the representative of the set
//to which x belongs.
int find_set(int x)
{

    if(par[x]==x)
        return x;
    else
        return par[x]=find_set(par[x]);
}

//Returns the size of set that the ith vertex is in
int sizeofSet(int i) {
    return SZ[find_set(i)];
}

bool merge_sets(int x,int y)
{
    int rx=find_set(x),ry=find_set(y);
    if(rx==ry)
        return 0;
    else{
        num_sets--;
        if(Rank[rx]==Rank[ry])// Anyone can be the others' parent
            par[ry]=rx,Rank[rx]++, SZ[rx]+= SZ[ry];
        else if(Rank[rx]<Rank[ry])
            par[rx]=ry, SZ[ry]+= SZ[rx];
        else
            par[ry]=rx, SZ[rx]+=SZ[ry];
            return 1;
    }
}

struct trienode {
    int idx;
    int cnt;
    int ar[2];
    trienode(int _idx = 0)
        :idx(_idx), cnt(0), ar{NULL, NULL}{}
};

//0th node is the NULL node
int num = 1;
trienode node[30*N];

inline bool bit(int x, int b) {
    return (x >> b) & 1;
}

struct Trie {
    const int bits = 30; //# bits in the number
    int root = num++;
    void insert(int x, int idx) {
        int curr = root;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            if(node[curr].ar[b] == NULL)
                node[curr].ar[b] = num++;
            curr = node[curr].ar[b];
            node[curr].cnt++;
        }
        node[curr].idx = idx;
    }

    int query(int x) {
        int curr = root;
        int ans = 0;
        for(int i = bits-1; i >= 0; i--) {
            int bx = bit(x, i);
            if(node[curr].ar[bx])
                curr = node[curr].ar[bx], ans |= bx << i;
            else
                curr = node[curr].ar[!bx], ans |= !bx << i;
        }
        // trace(x, ans, node[curr].idx);
        return node[curr].idx;
    }

    void erase(int x) {
        int curr = root;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            node[node[curr].ar[b]].cnt--;
            if(node[node[curr].ar[b]].cnt == 0) {
                node[curr].ar[b] = NULL;
                return;
            }
            curr = node[curr].ar[b];
        }
    }
};

vi adj[N];
int a[N];
ll ans;

main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/tarun/Desktop/input.txt", "r", stdin);
     // freopen("/home/tarun/Desktop/output.txt", "w", stdout);
    #endif
    sync;
    clock_t clk = clock();
    cerr << "I will return...\n";

    cin >> n;
    rep(i, 0, n) cin >> a[i];

    // trace(n);
    // rep(i, 0, n) trace(i, a[i]);

    sort(a, a + n);
    n = unique(a, a + n) - a;

    init();
    Trie T;

    rep(i, 0, n) T.insert(a[i], i);

    while(num_sets > 1) {
        rep(i, 0, n) adj[i].clear();
        rep(i, 0, n) adj[find_set(i)].pb(i);

        rep(i, 0, n) {
            if(adj[i].empty()) continue;
            for(int j : adj[i]) {
                // trace(j, a[j], T.query(a[j]));
                T.erase(a[j]);
            }
            int mnw;
            pii mnp;
            mnw = 2e9;

            for (int j : adj[i]) {
                int k = T.query(a[j]);
                int x = a[j] ^ a[k];
                if(x < mnw) {
                    mnw = x;
                    mnp = {j, k};
                }
            }
            int x, y; tie(x, y) = mnp;
            if(merge_sets(x, y)) ans += a[x] ^ a[y];

            for(int j : adj[i]) T.insert(a[j], j);
        }
    }

    cout << ans << '\n';

    cerr << "...don't you ever hang your head.\n";
    cerr << "Time (in ms): " << (double)(clock() - clk) * 1000.0 / cps << '\n';
}

//Compile using:
//g++ -o filename.exe --std=c++11 filename.cpp
//Use -D CP for defining a macro CP in the local environment


//I/O
#include<iostream>
#include<sstream>
//Containers
#include<deque>
#include<initializer_list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<string>
#include<unordered_map>
#include<unordered_set>
#include<vector>
//C library
#include<cmath>
#include<cassert>
#include<cctype>
#include<climits>
#include<cmath>
#include<cstddef>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
//Miscellaneous
#include<algorithm>
#include<bitset>
#include<complex>
#include<functional>
#include<iomanip>
#include<iterator>
#include<limits>
#include<numeric>
#include<random>
#include<tuple>
#include<utility>

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>

#define en '\n'
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define repi(i, a, b) for(int i=(a); i>(b); i--)
#define db(x) (cerr << #x << ": " << (x) << '\n')
#define sync ios_base::sync_with_stdio(false), cin.tie(NULL)
#define tests(t) int t; cin >> t; while(t--)
#define iceil(n, x) (((n) + (x) - 1) / (x))
#define ll long long
#define gcd __gcd
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define sz size()
#define all(v) (v).begin(), (v).end()
#define uni(v) sort(all(v)); (v).erase(unique(all(v)), (v).end());
#define pii pair<int, int>
#define vi vector<int>
#define vpii vector<pii>
#define vvi vector<vi>
#define fi first
#define se second
#define umap unordered_map
#define uset unordered_set
#define pqueue priority_queue
#define si(a) scanf("%d", &a)
#define sll(a) scanf("%lld", &a)
#define bitcount(x) __builtin_popcount(x)
#define cps CLOCKS_PER_SEC
#define PI acos(-1.0)
#define EPS 1e-9
#define mod 1000000007
using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cerr << name << " : " << arg1 << '\n';
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
using maxpq = priority_queue<T>;

//All indexing is 0-based
//using namespace __gnu_pbds;
//typedef tree<int, null_type, less<int>, rb_tree_tag,
             //tree_order_statistics_node_update> ordered_set;
//methods: find_by_order(k); & order_of_key(k);
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

template<typename T>
void printv(const vector<T>& v) { for(auto i : v) cerr << i << ' '; cerr << '\n'; }

//Returns no. of values x for which ceil(n / x) == y (y must be > 1).
inline ll CC(ll n, ll y) { return iceil(n, y-1) - iceil(n, y); }

//Returns no. of values x for which floor(n / x) == y
inline ll FF(ll n, ll y) { return n / y - n / (y+1); }

inline ll gcd(ll a, ll b) { return !b ? a: gcd(b, a%b); }

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c;}
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c;}
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p;}

#define N 200005
//#define int ll
//#define trace(...) 42

//SZ[i]: size of the set that the ith element is a root of

//Only valid for root elements

int par[N], Rank[N], SZ[N];

int num_sets;

int n; //number of vertices

//Rank[x] is an upper bound to the height

//of the subtree roted at node x.

void make_set(int x)

{

	num_sets++;

	par[x]=x;

	Rank[x]=0;

	SZ[x] = 1;

}

void init() {

	num_sets = 0;

	for(int i = 0; i < n; i++) make_set(i);

}

//returns the representative of the set

//to which x belongs.

int find_set(int x)

{

	if(par[x]==x)

		return x;

	else

		return par[x]=find_set(par[x]);

}

//Returns the size of set that the ith vertex is in

int sizeofSet(int i) {

	return SZ[find_set(i)];

}

bool merge_sets(int x,int y)

{

	int rx=find_set(x),ry=find_set(y);

	if(rx==ry)

		return 0;

	else{

		num_sets--;

		if(Rank[rx]==Rank[ry])// Anyone can be the others' parent

			par[ry]=rx,Rank[rx]++, SZ[rx]+= SZ[ry];

		else if(Rank[rx]<Rank[ry])

			par[rx]=ry, SZ[ry]+= SZ[rx];

		else

			par[ry]=rx, SZ[rx]+=SZ[ry];

			return 1;
	}

}

struct trienode {

    bool eow = 0;

    int idx;
    int cnt = 0;

    trienode* ar[2] = {NULL, NULL};

};

inline bool bit(int x, int b) {

    return (x >> b) & 1;

}

struct Trie {

    const int bits = 32; //# bits in the number

    trienode* root = new trienode;

    void insert(int x, int idx) {

        trienode* curr = root;

        for(int i = bits-1; i >= 0; i--) {

            int b = bit(x, i);

            if(curr -> ar[b] == NULL)

                curr -> ar[b] = new trienode;

            curr = curr -> ar[b];

            curr -> cnt++;

        }

        curr -> eow = 1;

        curr -> idx = idx;
    }

    int query(int x) {

        trienode* curr = root;

        int ans = 0;

        for(int i = bits-1; i >= 0; i--) {

            if(!curr) return ans;

            int bx = bit(x, i);

            if(curr -> ar[bx])
                     curr = curr -> ar[bx];
             else
                    curr = curr -> ar[!bx];

        }

        return curr -> idx;

    }

    void erase(int x) {

        trienode* curr = root;

        for(int i = bits-1; i >= 0; i--) {

            int b = bit(x, i);

            (curr -> ar[b] -> cnt)--;

            if(curr -> ar[b] -> cnt == 0) {

                curr -> ar[b] = NULL;

                return;

            }

            curr = curr -> ar[b];

        }

    }

};

vi adj[N];
int a[N];
ll ans;

int32_t main()
{
    #ifndef ONLINE_JUDGE
        freopen("/storage/emulated/0/input.txt", "r", stdin);
    //freopen("/storage/emulated/0/output.txt", "w", stdout);
    #endif
    sync;
    clock_t clk = clock();
    cerr << "I will return...\n";

    cin >> n;
    rep(i, 0, n) cin >> a[i];

    sort(a, a + n);
    n = unique(a, a + n) - a;

    init();
    Trie T;

    rep(i, 0, n) T.insert(a[i], i);

    while(num_sets > 1) {
        fill_n(adj, n, vi());
        rep(i, 0, n) adj[find_set(i)].pb(i);

        rep(i, 0, n) {
            if(adj[i].empty()) continue;
            for(int j : adj[i]) T.erase(a[j]);
            int mnw;
            pii mnp;
            mnw = 2e9;

            for (int j : adj[i]) {
                int k = T.query(a[j]);
                int x = a[j] ^ a[k];
                if(x < mnw) {
                    mnw = x;
                    mnp = {j, k};
                }
            }
            int x, y; tie(x, y) = mnp;
            if(merge_sets(x, y)) ans += a[x] ^ a[y];

            for(int j : adj[i]) T.insert(a[j], j);
        }
    }

    cout << ans << en;

    cerr << "...don't you ever hang your head.\n";
    cerr << "Time (in ms): " << double(clock() - clk) * 1000.0 / cps << '\n';
}

//Compile using:
//g++ -o filename.exe --std=c++11 filename.cpp
//Use -D CP for defining a macro CP in the local environment


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define repi(i, a, b) for(int i=(a); i>(b); i--)
#define db(x) (cerr << #x << ": " << (x) << '\n')
#define sync ios_base::sync_with_stdio(false), cin.tie(NULL)
#define tests(t) int t; cin >> t; while(t--)
#define iceil(n, x) (((n) + (x) - 1) / (x))
#define ll long long
#define gcd __gcd
#define eb emplace_back
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define sz size()
#define all(v) (v).begin(), (v).end()
#define uni(v) sort(all(v)); (v).erase(unique(all(v)), (v).end())
#define pii pair<int, int>
#define vi vector<int>
#define vpii vector<pii>
#define vvi vector<vi>
#define fi first
#define se second
#define pqueue priority_queue
#define bitcount(x) __builtin_popcount(x)
#define cps CLOCKS_PER_SEC
#define PI acos(-1.0)
#define EPS 1e-9
#define mod 1000000007
using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cerr << name << " : " << arg1 << '\n';
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}

template<typename T1, typename T2>
ostream& operator << (ostream& os, const pair<T1, T2>& p) { return os << '(' << p.fi << ", " << p.se << ')'; }

template<typename T>
void printv(const T& v) { for(auto i : v) cerr << i << ' '; cerr << '\n'; }

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
using maxpq = priority_queue<T>;

//All indexing is 0-based
using namespace __gnu_pbds;
template<class key, class cmp = std::less<key>>
using ordered_set = tree<key, null_type, cmp, rb_tree_tag, tree_order_statistics_node_update>;
//methods: find_by_order(k); & order_of_key(k);
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar

template<class key, class value, class cmp = std::less<key>>
using ordered_map = tree<key, value, cmp, rb_tree_tag, tree_order_statistics_node_update>;

//Returns no. of values x for which ceil(n / x) == y (y must be > 1).
inline ll CC(ll n, ll y) { return iceil(n, y-1) - iceil(n, y); }

//Returns no. of values x for which floor(n / x) == y
inline ll FF(ll n, ll y) { return n / y - n / (y+1); }

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

#define N 200005
// #define int ll
// #define trace(...) 42

//SZ[i]: size of the set that the ith element is a root of
//Only valid for root elements
int par[N], Rank[N], SZ[N];
int num_sets;
int n; //number of vertices
//Rank[x] is an upper bound to the height
//of the subtree roted at node x.
void make_set(int x)
{
    num_sets++;
    par[x]=x;
    Rank[x]=0;
    SZ[x] = 1;
}

void init() {
    num_sets = 0;
    for(int i = 0; i < n; i++) make_set(i);
}

//returns the representative of the set
//to which x belongs.
int find_set(int x)
{

    if(par[x]==x)
        return x;
    else
        return par[x]=find_set(par[x]);
}

//Returns the size of set that the ith vertex is in
int sizeofSet(int i) {
    return SZ[find_set(i)];
}

bool merge_sets(int x,int y)
{
    int rx=find_set(x),ry=find_set(y);
    if(rx==ry)
        return 0;
    else{
        num_sets--;
        if(Rank[rx]==Rank[ry])// Anyone can be the others' parent
            par[ry]=rx,Rank[rx]++, SZ[rx]+= SZ[ry];
        else if(Rank[rx]<Rank[ry])
            par[rx]=ry, SZ[ry]+= SZ[rx];
        else
            par[ry]=rx, SZ[rx]+=SZ[ry];
            return 1;
    }
}

struct trienode {
    int idx;
    int cnt;
    int ar[2];
    trienode(int _idx = 0)
        :idx(_idx), cnt(0), ar{NULL, NULL}{}
};

//0th node is the NULL node
int num = 1;
trienode node[30*N];

inline bool bit(int x, int b) {
    return (x >> b) & 1;
}

struct Trie {
    const int bits = 32; //# bits in the number
    int root = num++;
    void insert(int x, int idx) {
        int curr = root;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            if(node[curr].ar[b] == NULL)
                node[curr].ar[b] = num++;
            curr = node[curr].ar[b];
            node[curr].cnt++;
        }
        node[curr].idx = idx;
    }

    int query(int x) {
        int curr = root;
        int ans = 0;
        for(int i = bits-1; i >= 0; i--) {
            int bx = bit(x, i);
            if(node[node[curr].ar[bx]].cnt)
                curr = node[curr].ar[bx], ans |= bx << i;
            else
                curr = node[curr].ar[!bx], ans |= !bx << i;
        }
        // trace(x, ans, node[curr].idx);
        return node[curr].idx;
    }

    void erase(int x) {
        int curr = root;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            node[node[curr].ar[b]].cnt--;
            curr = node[curr].ar[b];
        }
    }
};

vi adj[N];
int a[N];
ll ans;

main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/tarun/Desktop/input.txt", "r", stdin);
     // freopen("/home/tarun/Desktop/output.txt", "w", stdout);
    #endif
    sync;
    clock_t clk = clock();
    cerr << "I will return...\n";

    cin >> n;
    rep(i, 0, n) cin >> a[i];

    // trace(n);
    // rep(i, 0, n) trace(i, a[i]);

    sort(a, a + n);
    n = unique(a, a + n) - a;

    init();
    Trie T;

    rep(i, 0, n) T.insert(a[i], i);

    while(num_sets > 1) {
        rep(i, 0, n) adj[i].clear();
        rep(i, 0, n) adj[find_set(i)].pb(i);

        rep(i, 0, n) {
            if(adj[i].empty()) continue;
            for(int j : adj[i]) {
                // trace(j, a[j], T.query(a[j]));
                T.erase(a[j]);
            }
            int mnw;
            pii mnp;
            mnw = 2e9;

            for (int j : adj[i]) {
                int k = T.query(a[j]);
                int x = a[j] ^ a[k];
                if(x < mnw) {
                    mnw = x;
                    mnp = {j, k};
                }
            }
            int x, y; tie(x, y) = mnp;
            if(merge_sets(x, y)) ans += a[x] ^ a[y];

            for(int j : adj[i]) T.insert(a[j], j);
        }
    }

    cout << ans << '\n';

    cerr << "...don't you ever hang your head.\n";
    cerr << "Time (in ms): " << (double)(clock() - clk) * 1000.0 / cps << '\n';
}

//Compile using:
//g++ -o filename.exe --std=c++11 filename.cpp
//Use -D CP for defining a macro CP in the local environment


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define repi(i, a, b) for(int i=(a); i>(b); i--)
#define db(x) (cerr << #x << ": " << (x) << '\n')
#define sync ios_base::sync_with_stdio(false), cin.tie(NULL)
#define tests(t) int t; cin >> t; while(t--)
#define iceil(n, x) (((n) + (x) - 1) / (x))
#define ll long long
#define gcd __gcd
#define eb emplace_back
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define sz size()
#define all(v) (v).begin(), (v).end()
#define uni(v) sort(all(v)); (v).erase(unique(all(v)), (v).end())
#define pii pair<int, int>
#define vi vector<int>
#define vpii vector<pii>
#define vvi vector<vi>
#define fi first
#define se second
#define pqueue priority_queue
#define bitcount(x) __builtin_popcount(x)
#define cps CLOCKS_PER_SEC
#define PI acos(-1.0)
#define EPS 1e-9
#define mod 1000000007
using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cerr << name << " : " << arg1 << '\n';
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}

template<typename T1, typename T2>
ostream& operator << (ostream& os, const pair<T1, T2>& p) { return os << '(' << p.fi << ", " << p.se << ')'; }

template<typename T>
void printv(const T& v) { for(auto i : v) cerr << i << ' '; cerr << '\n'; }

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
using maxpq = priority_queue<T>;

//All indexing is 0-based
using namespace __gnu_pbds;
template<class key, class cmp = std::less<key>>
using ordered_set = tree<key, null_type, cmp, rb_tree_tag, tree_order_statistics_node_update>;
//methods: find_by_order(k); & order_of_key(k);
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar

template<class key, class value, class cmp = std::less<key>>
using ordered_map = tree<key, value, cmp, rb_tree_tag, tree_order_statistics_node_update>;

//Returns no. of values x for which ceil(n / x) == y (y must be > 1).
inline ll CC(ll n, ll y) { return iceil(n, y-1) - iceil(n, y); }

//Returns no. of values x for which floor(n / x) == y
inline ll FF(ll n, ll y) { return n / y - n / (y+1); }

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

#define N 200005
#define int ll
// #define trace(...) 42

//SZ[i]: size of the set that the ith element is a root of
//Only valid for root elements
int par[N], Rank[N], SZ[N];
int num_sets;
int n; //number of vertices
//Rank[x] is an upper bound to the height
//of the subtree roted at node x.
void make_set(int x)
{
    num_sets++;
    par[x]=x;
    Rank[x]=0;
    SZ[x] = 1;
}

void init() {
    num_sets = 0;
    for(int i = 0; i < n; i++) make_set(i);
}

//returns the representative of the set
//to which x belongs.
int find_set(int x)
{

    if(par[x]==x)
        return x;
    else
        return par[x]=find_set(par[x]);
}

//Returns the size of set that the ith vertex is in
int sizeofSet(int i) {
    return SZ[find_set(i)];
}

bool merge_sets(int x,int y)
{
    int rx=find_set(x),ry=find_set(y);
    if(rx==ry)
        return 0;
    else{
        num_sets--;
        if(Rank[rx]==Rank[ry])// Anyone can be the others' parent
            par[ry]=rx,Rank[rx]++, SZ[rx]+= SZ[ry];
        else if(Rank[rx]<Rank[ry])
            par[rx]=ry, SZ[ry]+= SZ[rx];
        else
            par[ry]=rx, SZ[rx]+=SZ[ry];
            return 1;
    }
}

struct trienode {
    int idx;
    int cnt = 0;
    trienode* ar[2] = {NULL, NULL};
};

inline bool bit(int x, int b) {
    return (x >> b) & 1;
}

//Uses an improved version of erase() to prevent memory leak
//Rather than deleting nodes make the cnt = 0
struct Trie {
    const int bits = 32; //# bits in the number
    trienode* root = new trienode;
    void insert(int x, int idx) {
        trienode* curr = root;
        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            if(curr -> ar[b] == NULL)
                curr -> ar[b] = new trienode;
            curr = curr -> ar[b];
            curr -> cnt++;
        }
        assert(curr);
        curr -> idx = idx;
    }

    int query(int x) {
        trienode* curr = root;
        int ans = 0;
        for(int i = bits-1; i >= 0; i--) {
            int bx = bit(x, i);
            if(curr -> ar[bx] && curr -> ar[bx] -> cnt)
                curr = curr -> ar[bx], ans |= bx << i;
            else
                curr = curr -> ar[!bx], ans |= !bx << i;
        }
        assert(curr);
        return curr -> idx;
    }

    void erase(int x) {
        trienode* curr = root;
        vector<trienode*> v;

        for(int i = bits-1; i >= 0; i--) {
            int b = bit(x, i);
            (curr -> ar[b] -> cnt)--;
            curr = curr -> ar[b];
        }
    }
};

vi adj[N];
int a[N];
ll ans;

main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/tarun/Desktop/input.txt", "r", stdin);
     // freopen("/home/tarun/Desktop/output.txt", "w", stdout);
    #endif
    sync;
    clock_t clk = clock();
    cerr << "I will return...\n";

    cin >> n;
    rep(i, 0, n) cin >> a[i];

    // trace(n);
    // rep(i, 0, n) trace(i, a[i]);

    sort(a, a + n);
    n = unique(a, a + n) - a;

    init();
    Trie T;

    rep(i, 0, n) T.insert(a[i], i);

    while(num_sets > 1) {
        // trace(num_sets);
        rep(i, 0, n) adj[i].clear();
        rep(i, 0, n) adj[find_set(i)].pb(i);

        rep(i, 0, n) {
            if(adj[i].empty()) continue;
            for(int j : adj[i]) {
                T.erase(a[j]);
            }
            int mnw;
            pii mnp;
            mnw = 2e9;

            for (int j : adj[i]) {
                int k = T.query(a[j]);
                int x = a[j] ^ a[k];
                if(x < mnw) {
                    mnw = x;
                    mnp = {j, k};
                }
            }

            int x, y; tie(x, y) = mnp;
            if(merge_sets(x, y)) ans += a[x] ^ a[y];

            for(int j : adj[i]) T.insert(a[j], j);
        }
    }

    cout << ans << '\n';

    cerr << "...don't you ever hang your head.\n";
    cerr << "Time (in ms): " << (double)(clock() - clk) * 1000.0 / cps << '\n';
}

//Compile using:
//g++ -o filename.exe --std=c++11 filename.cpp
//Use -D CP for defining a macro CP in the local environment


//I/O
#include<iostream>
#include<sstream>
//Containers
#include<deque>
#include<initializer_list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<string>
#include<unordered_map>
#include<unordered_set>
#include<vector>
//C library
#include<cmath>
#include<cassert>
#include<cctype>
#include<climits>
#include<cmath>
#include<cstddef>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
//Miscellaneous
#include<algorithm>
#include<bitset>
#include<complex>
#include<functional>
#include<iomanip>
#include<iterator>
#include<limits>
#include<numeric>
#include<random>
#include<tuple>
#include<utility>

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>

#define en '\n'
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define repi(i, a, b) for(int i=(a); i>(b); i--)
#define db(x) (cerr << #x << ": " << (x) << '\n')
#define sync ios_base::sync_with_stdio(false), cin.tie(NULL)
#define tests(t) int t; cin >> t; while(t--)
#define iceil(n, x) (((n) + (x) - 1) / (x))
#define ll long long
#define gcd __gcd
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define sz size()
#define all(v) (v).begin(), (v).end()
#define uni(v) sort(all(v)); (v).erase(unique(all(v)), (v).end());
#define pii pair<int, int>
#define vi vector<int>
#define vpii vector<pii>
#define vvi vector<vi>
#define fi first
#define se second
#define umap unordered_map
#define uset unordered_set
#define pqueue priority_queue
#define si(a) scanf("%d", &a)
#define sll(a) scanf("%lld", &a)
#define bitcount(x) __builtin_popcount(x)
#define cps CLOCKS_PER_SEC
#define PI acos(-1.0)
#define EPS 1e-9
#define mod 1000000007
using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
    cerr << name << " : " << arg1 << '\n';
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
    const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<typename T>
using maxpq = priority_queue<T>;

//All indexing is 0-based
//using namespace __gnu_pbds;
//typedef tree<int, null_type, less<int>, rb_tree_tag,
             //tree_order_statistics_node_update> ordered_set;
//methods: find_by_order(k); & order_of_key(k);
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

template<typename T>
void printv(const vector<T>& v) { for(auto i : v) cerr << i << ' '; cerr << '\n'; }

//Returns no. of values x for which ceil(n / x) == y (y must be > 1).
inline ll CC(ll n, ll y) { return iceil(n, y-1) - iceil(n, y); }

//Returns no. of values x for which floor(n / x) == y
inline ll FF(ll n, ll y) { return n / y - n / (y+1); }

inline ll gcd(ll a, ll b) { return !b ? a: gcd(b, a%b); }

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c;}
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c;}
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p;}

#define N 200005
#define int ll
//#define trace(...) 42

//SZ[i]: size of the set that the ith element is a root of

//Only valid for root elements

int par[N], Rank[N], SZ[N];

int num_sets;

int n; //number of vertices

//Rank[x] is an upper bound to the height

//of the subtree roted at node x.

void make_set(int x)

{

	num_sets++;

	par[x]=x;

	Rank[x]=0;

	SZ[x] = 1;

}

void init() {

	num_sets = 0;

	for(int i = 0; i < n; i++) make_set(i);

}

//returns the representative of the set

//to which x belongs.

int find_set(int x)

{

	if(par[x]==x)

		return x;

	else

		return par[x]=find_set(par[x]);

}

//Returns the size of set that the ith vertex is in

int sizeofSet(int i) {

	return SZ[find_set(i)];

}

bool merge_sets(int x,int y)

{

	int rx=find_set(x),ry=find_set(y);

	if(rx==ry)

		return 0;

	else{

		num_sets--;

		if(Rank[rx]==Rank[ry])// Anyone can be the others' parent

			par[ry]=rx,Rank[rx]++, SZ[rx]+= SZ[ry];

		else if(Rank[rx]<Rank[ry])

			par[rx]=ry, SZ[ry]+= SZ[rx];

		else

			par[ry]=rx, SZ[rx]+=SZ[ry];

			return 1;
	}

}

struct trienode {

    bool eow = 0;

    int idx;
    int cnt = 0;

    trienode* ar[2] = {NULL, NULL};

};

inline bool bit(int x, int b) {

    return (x >> b) & 1;

}

struct Trie {

    const int bits = 32; //# bits in the number

    trienode* root = new trienode;

    void insert(int x, int idx) {

        trienode* curr = root;

        for(int i = bits-1; i >= 0; i--) {

            int b = bit(x, i);

            if(curr -> ar[b] == NULL)

                curr -> ar[b] = new trienode;

            curr = curr -> ar[b];

            curr -> cnt++;

        }

        curr -> eow = 1;

        curr -> idx = idx;
    }

    int query(int x) {

        trienode* curr = root;

        int ans = 0;

        for(int i = bits-1; i >= 0; i--) {

            if(!curr) return ans;

            int bx = bit(x, i);

            if(curr -> ar[bx])
                     curr = curr -> ar[bx];
             else
                    curr = curr -> ar[!bx];

        }

        return curr -> idx;

    }

    void erase(int x) {

        trienode* curr = root;

        for(int i = bits-1; i >= 0; i--) {

            int b = bit(x, i);

            (curr -> ar[b] -> cnt)--;

            if(curr -> ar[b] -> cnt == 0) {

                curr -> ar[b] = NULL;

                return;

            }

            curr = curr -> ar[b];

        }

    }

};

vi adj[N];
int a[N], ans;

int32_t main()
{
    #ifndef ONLINE_JUDGE
        freopen("/storage/emulated/0/input.txt", "r", stdin);
    //freopen("/storage/emulated/0/output.txt", "w", stdout);
    #endif
    sync;
    clock_t clk = clock();
    cerr << "I will return...\n";

    cin >> n;
    rep(i, 0, n) cin >> a[i];

    sort(a, a + n);
    n = unique(a, a + n) - a;

    init();
    Trie T;

    rep(i, 0, n) T.insert(a[i], i);

    while(num_sets > 1) {
        fill_n(adj, n, vi());
        rep(i, 0, n) adj[find_set(i)].pb(i);

        rep(i, 0, n) {
            if(adj[i].empty()) continue;
            for(int j : adj[i]) T.erase(a[j]);
            int mnw;
            pii mnp;
            mnw = 2e9;

            for (int j : adj[i]) {
                int k = T.query(a[j]);
                int x = a[j] ^ a[k];
                if(x < mnw) {
                    mnw = x;
                    mnp = {j, k};
                }
            }
            int x, y; tie(x, y) = mnp;
            if(merge_sets(x, y)) ans += a[x] ^ a[y];

            for(int j : adj[i]) T.insert(a[j], j);
        }
    }

    cout << ans << en;

    cerr << "...don't you ever hang your head.\n";
    cerr << "Time (in ms): " << double(clock() - clk) * 1000.0 / cps << '\n';
}

//Compile using:
//g++ -o filename.exe --std=c++11 filename.cpp
//Use -D CP for defining a macro CP in the local environment


//be name khoda
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define F first
#define S second

const int maxn = 2e5+10;
const ll inf = 1e9+10;

int pa[maxn];
int get_par(int v)
{
    if(pa[v] == v) return v;
    return pa[v] = get_par(pa[v]);
}

set<pair<int,int>> s;
vector<int> comp[maxn];
void dsu(int u, int v)
{
    u = get_par(u);
    v = get_par(v);

    if(u == v) return;

    if(comp[u].size() > comp[v].size()) swap(u,v);

    s.erase({comp[u].size(),u});
    s.erase({comp[v].size(),v});

    pa[u] = v;
    for(auto x : comp[u])
        comp[v].push_back(x);
    s.insert({comp[v].size(),v});
}

const int N = 6e6+10;

struct trie
{
    int par[N], ch[N][2], last;

    trie()
    {
        memset(par, 0, sizeof par);
        memset(ch, 0, sizeof ch);
        last = 1;
    }

    void add(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            if(ch[v][X] == 0)
            {
                last++;
                ch[v][X] = last;
            }

            par[ch[v][X]] = v;
            v = ch[v][X];
        }
    }

    void del(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            v = ch[v][X];
        }

        for(int i = 0; i <= 30; i++)
        {
            bool X = x & (1<<i);
            int u = par[v];
            ch[u][X] = 0;
            if(ch[u][!X] != 0) break;
            v = u;
        }
    }

    int get(int x)
    {
        ll ans = 0;
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);

            if(ch[v][X] != 0)
                v = ch[v][X];
            else
            {
                v = ch[v][!X];
                ans += (1<<i);
            }
        }
        return ans;
    }
} trie;

map<int,int> mp;
int rmp[maxn];
int n;

signed main()
{
    cin>> n;
    for(int i = 1, x; i <= n; i++)
    {
        cin>> x;
        if(!mp.count(x))
        {
            mp.insert({x,i});
            rmp[i] = x;
            s.insert({1,i});
            pa[i] = i;
            comp[i].push_back(i);
            trie.add(x);
        }
    }

    ll ans = 0;
    while(s.size() > 1)
    {
        int v = s.begin()->second;
        for(auto x : comp[v])
            trie.del(rmp[x]);

        pair<int,int> mn = {inf,inf};
        for(auto x : comp[v])
        {
            int X = trie.get(rmp[x]);
            if(X <= mn.F)
                mn = {X,x};
        }

        int X = mn.F, x = mn.S;
        ans += X;
        dsu(x,mp[(rmp[x]^X)]);

        for(auto x : comp[v])
            trie.add(rmp[x]);
    }
    cout<< ans;
}


//be name khoda
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define F first
#define S second

const int maxn = 2e5+10;
const ll inf = 1e9+10;

int pa[maxn], cur;
int get_par(int v)
{
    if(pa[v] == v) return v;
    return pa[v] = get_par(pa[v]);
}

set<pair<int,int>> s;
vector<int> comp[maxn];
void dsu(int u, int v)
{
    u = get_par(u);
    v = get_par(v);

    if(u == v) return;

    if(comp[u].size() > comp[v].size()) swap(u,v);

    s.erase({comp[u].size(),u});
    s.erase({comp[v].size(),v});

    pa[u] = v;
    for(auto x : comp[u])
        comp[v].push_back(x);
    s.insert({comp[v].size(),v});
    cur = u;
}

const int N = 2e7+10;

struct trie
{
    int par[N], ch[N][2], last;

    trie()
    {
        memset(par, 0, sizeof par);
        memset(ch, 0, sizeof ch);
        last = 1;
    }

    void add(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            if(ch[v][X] == 0)
            {
                last++;
                ch[v][X] = last;
            }

            par[ch[v][X]] = v;
            v = ch[v][X];
        }
    }

    void del(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            v = ch[v][X];
        }

        for(int i = 0; i <= 30; i++)
        {
            bool X = x & (1<<i);
            int u = par[v];
            ch[u][X] = 0;
            if(ch[u][!X] != 0) break;
            v = u;
        }
    }

    int get(int x)
    {
        ll ans = 0;
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);

            if(ch[v][X] != 0)
                v = ch[v][X];
            else
            {
                v = ch[v][!X];
                ans += (1<<i);
            }
        }
        return ans;
    }
} trie;

map<int,int> mp;
int rmp[maxn];
int n;

signed main()
{
    cin>> n;
    for(int i = 1, x; i <= n; i++)
    {
        cin>> x;
        if(!mp.count(x))
        {
            mp.insert({x,i});
            rmp[i] = x;
            s.insert({1,i});
            pa[i] = i;
            comp[i].push_back(i);
            trie.add(x);
        }
    }

    ll ans = 0;
    while(s.size() > 1)
    {
        int v = s.begin()->second;
        for(auto x : comp[v])
            trie.del(rmp[x]);

        pair<int,int> mn = {inf,inf};
        for(auto x : comp[v])
        {
            int X = trie.get(rmp[x]);
            if(X <= mn.F)
                mn = {X,x};
        }

        int X = mn.F, x = mn.S;
        ans += X;
        dsu(x,mp[(rmp[x]^X)]);

        for(auto x : comp[v])
            trie.add(rmp[x]);

        comp[cur].clear();
    }
    cout<< ans;
}


//be name khoda
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define F first
#define S second

const int maxn = 2e5+10;
const ll inf = 1e9+10;

int pa[maxn];
int get_par(int v)
{
    if(pa[v] == v) return v;
    return pa[v] = get_par(pa[v]);
}

set<pair<int,int>> s;
vector<int> comp[maxn];
void dsu(int u, int v)
{
    u = get_par(u);
    v = get_par(v);

    if(u == v) return;

    if(comp[u].size() > comp[v].size()) swap(u,v);

    s.erase({comp[u].size(),u});
    s.erase({comp[v].size(),v});

    pa[u] = v;
    for(auto x : comp[u])
        comp[v].push_back(x);
    comp[u].clear();
    s.insert({comp[v].size(),v});
}

const int N = 2e7+10;

struct trie
{
    int par[N], ch[N][2], last;

    trie()
    {
        memset(par, 0, sizeof par);
        memset(ch, 0, sizeof ch);
        last = 1;
    }

    void add(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            if(ch[v][X] == 0)
            {
                last++;
                ch[v][X] = last;
            }

            par[ch[v][X]] = v;
            v = ch[v][X];
        }
    }

    void del(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            v = ch[v][X];
        }

        for(int i = 0; i <= 30; i++)
        {
            bool X = x & (1<<i);
            int u = par[v];
            ch[u][X] = 0;
            if(ch[u][!X] != 0) break;
            v = u;
        }
    }

    int get(int x)
    {
        ll ans = 0;
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);

            if(ch[v][X] != 0)
                v = ch[v][X];
            else
            {
                v = ch[v][!X];
                ans += (1<<i);
            }
        }
        return ans;
    }
} trie;

map<int,int> mp;
int rmp[maxn];
int n;

signed main()
{
    cin>> n;
    for(int i = 1, x; i <= n; i++)
    {
        cin>> x;
        if(!mp.count(x))
        {
            mp.insert({x,i});
            rmp[i] = x;
            s.insert({1,i});
            pa[i] = i;
            comp[i].push_back(i);
            trie.add(x);
        }
    }

    ll ans = 0;
    while(s.size() > 1)
    {
        int v = s.begin()->second;
        for(auto x : comp[v])
            trie.del(rmp[x]);

        pair<int,int> mn = {inf,inf};
        for(auto x : comp[v])
        {
            int X = trie.get(rmp[x]);
            if(X <= mn.F)
                mn = {X,x};
        }

        int X = mn.F, x = mn.S;
        ans += X;
        dsu(x,mp[(rmp[x]^X)]);

        for(auto x : comp[v])
            trie.add(rmp[x]);
    }
    cout<< ans;
}


//be name khoda
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define F first
#define S second

const int maxn = 2e5+10;
const ll inf = 1e9+10;

int pa[maxn];
int get_par(int v)
{
    if(pa[v] == v) return v;
    return pa[v] = get_par(pa[v]);
}

set<pair<int,int>> s;
vector<int> comp[maxn];
void dsu(int u, int v)
{
    u = get_par(u);
    v = get_par(v);

    if(u == v) return;

    if(comp[u].size() > comp[v].size()) swap(u,v);

    s.erase({comp[u].size(),u});
    s.erase({comp[v].size(),v});

    pa[u] = v;
    for(auto x : comp[u])
        comp[v].push_back(x);
    s.insert({comp[v].size(),v});
}

const int N = 2.3e7+10;

struct trie
{
    int par[N], ch[N][2], last;

    trie()
    {
        memset(par, 0, sizeof par);
        memset(ch, 0, sizeof ch);
        last = 1;
    }

    void add(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            if(ch[v][X] == 0)
            {
                last++;
                ch[v][X] = last;
            }

            par[ch[v][X]] = v;
            v = ch[v][X];
        }
    }

    void del(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            v = ch[v][X];
        }

        for(int i = 0; i <= 30; i++)
        {
            bool X = x & (1<<i);
            int u = par[v];
            ch[u][X] = 0;
            if(ch[u][!X] != 0) break;
            v = u;
        }
    }

    int get(int x)
    {
        ll ans = 0;
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);

            if(ch[v][X] != 0)
                v = ch[v][X];
            else
            {
                v = ch[v][!X];
                ans += (1<<i);
            }
        }
        return ans;
    }
} trie;

map<int,int> mp;
int rmp[maxn];
int n;

signed main()
{
    cin>> n;
    for(int i = 1, x; i <= n; i++)
    {
        cin>> x;
        if(!mp.count(x))
        {
            mp.insert({x,i});
            rmp[i] = x;
            s.insert({1,i});
            pa[i] = i;
            comp[i].push_back(i);
            trie.add(x);
        }
    }

    ll ans = 0;
    while(s.size() > 1)
    {
        int v = s.begin()->second;
        for(auto x : comp[v])
            trie.del(rmp[x]);

        pair<int,int> mn = {inf,inf};
        for(auto x : comp[v])
        {
            int X = trie.get(rmp[x]);
            if(X <= mn.F)
                mn = {X,x};
        }

        int X = mn.F, x = mn.S;
        ans += X;
        dsu(x,mp[(rmp[x]^X)]);

        for(auto x : comp[v])
            trie.add(rmp[x]);
    }
    cout<< ans;
}


//be name khoda
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define F first
#define S second

const int maxn = 2e5+10;
const ll inf = 1e9+10;

const int N = 6e6+10;

struct trie
{
    int ch[N][2], last;
    vector<int> leaf[maxn];

    trie()
    {
        memset(ch, 0, sizeof ch);
        last = 1;
    }

    void add(int x)
    {
        int v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            if(ch[v][X] == 0)
            {
                last++;
                ch[v][X] = last;
            }

            v = ch[v][X];
        }

        v = 1;
        for(int i = 30; i >= 0; i--)
        {
            bool X = x & (1<<i);
            leaf[v].push_back(x);
            v = ch[v][X];
        }
        leaf[v].push_back(x);
    }

    int get(int x, int v, int h)
    {
        ll ans = 0;
        for(int i = h; i >= 0; i--)
        {
            bool X = x & (1<<i);

            if(ch[v][X] != 0)
                v = ch[v][X];
            else
            {
                v = ch[v][!X];
                ans += (1<<i);
            }
        }
        return ans;
    }

    ll get_ans(int v, int h)
    {
        if(ch[v][0] == 0 && ch[v][1] == 0) return 0;
        if(ch[v][0] == 0) return get_ans(ch[v][1],h-1);
        if(ch[v][1] == 0) return get_ans(ch[v][0],h-1);

        ll ans = 0;
        ans += get_ans(ch[v][1],h-1);
        ans += get_ans(ch[v][0],h-1);

        int mn = inf;
        for(auto x : leaf[ch[v][1]])
            mn = min(mn, get(x,ch[v][0],h-1));

        return ans + mn + (1<<h);
    }
} trie;

int n;

signed main()
{
    cin>> n;
    for(int i = 1, x; i <= n; i++)
    {
        cin>> x;
        trie.add(x);
    }
    cout<< trie.get_ans(1,30);
}