#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct TrieNode {
int child[2];
TrieNode() { child[0] = child[1] = -1; }
};
struct BinaryTrie {
vector<TrieNode> trie;
int k; // 비트 길이 (트라이 깊이)
BinaryTrie(int _k) : k(_k) {
trie.clear();
trie.push_back(TrieNode()); // root
}
void insert(int x) {
int node = 0;
for (int bit = k-1; bit >= 0; --bit) {
int b = (x >> bit) & 1;
if (trie[node].child[b] == -1) {
trie[node].child[b] = (int)trie.size();
trie.push_back(TrieNode());
}
node = trie[node].child[b];
}
}
// DFS를 돌면서 각 리프(삽입된 값)에 대한 기여도 계산
ll dfs(int node, int depth, ll fixedMask, int fixedCount) {
// depth는 현재 처리 중인 비트 (루트에서 k-1 시작, 마지막 -1이 되면 리프)
int left = trie[node].child[0];
int right = trie[node].child[1];
if (left == -1 && right == -1) {
// 리프
// 현재 fixedMask = sum(2^j for j in 분기 발생 비트)
// fixedCount = |S_b|
int L = 1 << k;
ll freeCount = k - fixedCount;
// contrib = 2^(k - |S_b| - 1) * ((2^k - 1) - fixedMask)
ll powVal = (1LL << (freeCount - 1));
ll contrib = powVal * ((1LL << k) - 1 - fixedMask);
return contrib;
}
ll res = 0;
bool branching = (left != -1 && right != -1);
if (left != -1) {
res += dfs(left, depth - 1, fixedMask + (branching ? (1LL << depth) : 0), fixedCount + (branching ? 1 : 0));
}
if (right != -1) {
res += dfs(right, depth - 1, fixedMask + (branching ? (1LL << depth) : 0), fixedCount + (branching ? 1 : 0));
}
return res;
}
ll computeF() {
return dfs(0, k-1, 0, 0);
}
};
// dyadic decomposition
vector<pair<int,int>> decompose(int M) {
vector<pair<int,int>> blocks;
int cur = 0;
while (cur < M) {
int size = 1;
while (size <= M - cur) size <<= 1;
size >>= 1;
while (cur % size != 0) size >>= 1;
blocks.push_back({cur, __builtin_ctz(size)}); // base, k (k=log2(size))
cur += size;
}
return blocks;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, M;
cin >> N >> M;
vector<int> A(N);
for (int i = 0; i < N; i++) cin >> A[i];
ll answer = 0;
auto blocks = decompose(M);
for (auto [base, k] : blocks) {
int L = 1 << k;
// Step 1: B = A xor base
int hmin = INT_MAX;
for (int a : A) {
int v = a ^ base;
hmin = min(hmin, v >> k);
}
// Step 2: B' 집합
unordered_set<int> BpSet;
BpSet.reserve(N*2);
for (int a : A) {
int v = a ^ base;
if ((v >> k) == hmin) {
BpSet.insert(v & (L - 1));
}
}
// Step 3: 상위항
answer += (ll)(hmin << k) * L;
// Step 4: 하위항 F(k, B')
if (!BpSet.empty()) {
BinaryTrie trie(k);
for (int val : BpSet) trie.insert(val);
answer += trie.computeF();
}
}
cout << answer << "\n";
return 0;
}