#include <bits/stdc++.h>
using namespace std;
// debug /*{{{*/
#define debug(...) __dbg(#__VA_ARGS__, __VA_ARGS__)
template<typename T> concept Container = ranges::range<T> && !convertible_to<T, string_view>;
template<typename T, typename U> ostream& operator<<(ostream& out, const pair<T, U>& v);
template<typename... Args> ostream& operator<<(ostream& out, const tuple<Args...>& v);
template<Container T> ostream& operator<<(ostream& out, const T& v);
template<typename T, typename U>
ostream& operator<<(ostream& out, const pair<T, U>& v) {
out << '(' << v.first << ' ' << v.second << ')';
return out;
}
template<typename... Args>
ostream& operator<<(ostream& out, const tuple<Args...>& v) {
string _;
out << '(';
apply([&](auto&&... x) { (..., (out << _ << x, _ = " ")); }, v);
out << ')';
return out;
}
template<Container T>
ostream& operator<<(ostream& out, const T& v) {
string _;
out << '(';
for (auto i : v) out << _ << i, _ = " ";
out << ')';
return out;
}
template<typename ...Args>
void __dbg(string s, Args&&... x) {
string _;
cerr << '(' << s << ") : ";
(..., (cerr << _ << x, _ = ", "));
cerr << endl;
}
/*}}}*/
using i64 = long long;
auto naive = [](int n, i64 k, auto v) {
vector c(0, 0);
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
c.push_back(v[i] ^ v[j]);
}
}
nth_element(c.begin(), c.begin() + k - 1, c.end());
return c[k - 1];
};
auto sol = [](int n, i64 k, auto v) {
vector l(1, -1), r(1, -1);
vector cnt(1, 0);
int sz = 1;
for (int i = 0; i < n; i++) {
int x = v[i];
cnt[0]++;
for (int bit = 29, pos = 0; bit >= 0; bit--) {
if (x >> bit & 1) swap(l[pos], r[pos]);
if (l[pos] == -1) {
l.push_back(-1);
r.push_back(-1);
cnt.push_back(0);
sz++;
l[pos] = sz - 1;
}
int npos = l[pos];
if (x >> bit & 1) swap(l[pos], r[pos]);
pos = npos;
cnt[pos]++;
}
}
auto query = [&](int i, int x) {
/*
int ret = 0;
for (int val : v) if ((val ^ x) <= i) ret++;
return ret;
*/
auto rec = [&](const auto& self, int node, int node_l, int node_r, int bit) -> int {
assert(node_l <= i);
if (i == node_r) return cnt[node];
if (x >> bit & 1) swap(l[node], r[node]);
int mid = (node_l + node_r) / 2;
int ret = 0;
if (i <= mid) {
if (l[node] != -1) ret += self(self, l[node], node_l, mid, bit - 1);
}
else {
if (l[node] != -1) ret += cnt[l[node]];
if (r[node] != -1) ret += self(self, r[node], mid + 1, node_r, bit - 1);
}
if (x >> bit & 1) swap(l[node], r[node]);
return ret;
};
return rec(rec, 0, 0, (1 << 30) - 1, 29);
};
auto f = [&](int x) {
i64 ret = 0;
for (int i = 0; i < n; i++) ret += query(x, v[i]) - 1;
ret /= 2;
return ret;
};
int lo = -1, hi = 1 << 30;
while (lo + 1 < hi) {
int mid = (lo + hi) / 2;
if (f(mid) < k) lo = mid;
else hi = mid;
}
return hi;
};
// vgen /*{{{*/
auto gen_rand = [](int l, int r) {
static mt19937 rd(0x814814);
return uniform_int_distribution(l, r)(rd);
};
auto gen = [] {
int lim = 10;
int n = gen_rand(2, 6);
i64 k = gen_rand(1, n * (n - 1) / 2);
vector v(n, 0);
for (int i = 0; i < n; i++) v[i] = gen_rand(0, lim);
return tuple(n, k, v);
};
auto test = [] {
for (int iter = 0; iter < 100'000; iter++) {
if (iter % 1'000 == 0) debug(iter);
auto [n, k, v] = gen();
auto r1 = naive(n, k, v);
auto r2 = sol(n, k, v);
if (r1 == r2) continue;
debug(n);
debug(v);
debug(r1);
debug(r2);
break;
}
exit(0);
};
/*}}}*/
int main() {
cin.tie(0)->sync_with_stdio(0);
int n; cin >> n;
i64 k; cin >> k;
vector v(n, 0);
for (int i = 0; i < n; i++) cin >> v[i];
cout << sol(n, k, v) << '\n';
}