看错题了……OR 看成 XOR。
容易发现 gcd 是单调递减的,\text{or} 是单调递增的,所以可以分别用 ST 表维护,再二分。
复杂度 O(n \log^2 n)。
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5, INF = 0x3f3f3f3f;
int n, k, a[N];
int f[N][20], g[N][20], lg[N];
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
void initgcd() {
lg[1] = 0; for (int i = 2; i <= n; i++) lg[i] = lg[i >> 1] + 1;
for (int j = 1; j <= n; j++) g[j][0] = a[j];
for (int i = 1; i <= 19; i++)
for (int j = 1; j <= n && j + (1 << i - 1) <= n; j++) g[j][i] = gcd(g[j][i - 1], g[j + (1 << i - 1)][i - 1]);
}
int querygcd(int l, int r) {
int len = lg[r - l + 1];
return gcd(g[l][len], g[r - (1 << len) + 1][len]);
}
void initor() {
for (int j = 1; j <= n; j++) f[j][0] = a[j];
for (int i = 1; i <= 19; i++)
for (int j = 1; j <= n && j + (1 << i - 1) <= n; j++) f[j][i] = f[j][i - 1] | f[j + (1 << i - 1)][i - 1];
}
int queryor(int l, int r) {
int len = lg[r - l + 1];
return f[l][len] | f[r - (1 << len) + 1][len];
}
long long ans = 0;
int getsum(int lt, int L, int R, int eq) {
int l1 = L, r1 = R;
while (l1 < r1) {
int mid = l1 + r1 >> 1;
if (queryor(lt, mid) < eq) l1 = mid + 1;
else r1 = mid;
}
if (queryor(lt, l1) != eq) return 0;
int l2 = L, r2 = R;
while (l2 < r2) {
int mid = l2 + r2 + 1 >> 1;
if (queryor(lt, mid) > eq) r2 = mid - 1;
else l2 = mid;
}
return l2 - l1 + 1;
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
initgcd(), initor();
for (int i = 1; i <= n; i++) {
int now = i;
while (1) {
int l = now, r = n, lst = querygcd(i, now);
while (l < r) {
int mid = l + r + 1 >> 1;
if (querygcd(i, mid) == lst) l = mid;
else r = mid - 1;
}
int val = lst ^ k;
ans += getsum(i, now, l, val);
// for (int j = now; j <= l; j++) {
// int sum = 0; for (int k = i; k <= j; k++) sum |= a[k];
// ans += (sum == val);
// }
if (l == n) break;
now = l + 1;
}
}
printf("%lld\n", ans);
return 0;
}