#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<vector> #include<algorithm> #define get(x) ((x) / len) using namespace std; const int N = 1e5 + 5; typedef long long ll;
ll ans[N]; int w[N], g[N], f[N], len; struct query1 { int id, l, r; ll res; bool operator < (const query1 a) const { int x = get(l), y = get(a.l); if (x != y) return x < y; return r < a.r; } } q[N]; struct query2 { int id, l, r, t; }; vector<query2> rang[N]; vector<int> num;
int get_count(int x) { int res = 0; while (x) res += x & 1, x >>= 1; return res; }
int main() { int n, m, k; scanf("%d%d%d", &n, &m, &k); for (int i = 1; i <= n; i++) scanf("%d", &w[i]); for (int i = 1; i <= m; i++) scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i; for (int i = 0; i < 1 << 14; i++) if (get_count(i) == k) num.push_back(i); for (int i = 1; i <= n; i++) { for (int j = 0; j < num.size(); j++) g[w[i] ^ num[j]]++; f[i] = g[w[i + 1]]; } len = sqrt(n); sort(q + 1, q + 1 + m); for (int i = 1, l = 1, r = 0; i <= m; i++) { int L = q[i].l, R = q[i].r; if (r < R) rang[l - 1].push_back(query2({i, r + 1, R, -1})); while (r < R) q[i].res += f[r++]; if (r > R) rang[l - 1].push_back(query2({i, R + 1, r, 1})); while (r > R) q[i].res -= f[r - 1], r--; if (l < L) rang[r].push_back(query2({i, l, L - 1, -1})); while (l < L) q[i].res += f[l - 1] + !k, l++; if (l > L) rang[r].push_back(query2({i, L, l - 1, 1})); while (l > L) q[i].res -= f[l - 2] + !k, l--; } memset(g, 0, sizeof(g)); for (int i = 1; i <= n; i++) { for (int j = 0; j < num.size(); j++) g[w[i] ^ num[j]]++; for (int j = 0; j < rang[i].size(); j++) { query2& a = rang[i][j]; int l = a.l, r = a.r, t = a.t, id = a.id; for (int x = l; x <= r; x++) q[id].res += g[w[x]] * t; } } for (int i = 1; i <= m; i++) q[i].res += q[i - 1].res, ans[q[i].id] = q[i].res; for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]); return 0; }