给定一个长度为 n𝑛 的非负整数序列 a1,a2,…,an𝑎1,𝑎2,…,𝑎𝑛。
请你计算,一共有多少个该序列的连续子序列满足:子序列内的所有元素的按位异或和不小于 k𝑘。
输入格式
第一行包含两个整数 n,k𝑛,𝑘。
第二行包含 n𝑛 个整数 a1,a2,…,an𝑎1,𝑎2,…,𝑎𝑛。
输出格式
一个整数,表示满足条件的连续子序列的数量。
数据范围
前 44 个测试点满足 1≤n≤31≤𝑛≤3。
所有测试点满足 1≤n≤1061≤𝑛≤106,1≤k≤1091≤𝑘≤109,0≤ai≤1090≤𝑎𝑖≤109。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
int n, k;
const int N = 30000000;
int cont[N], son[N][2], idex=0;
typedef long long LL;
using namespace std;
void insert(int x)
{
int p = 0;//得到树的层数,方便找到节点
for (int i = 29; i >=0; i--)
{
int u = x >> i & 1;
if (!son[p][u])son[p][u] = ++idex;//初始画节点
p = son[p][u];//更新层数
cont[p]++;//记录这一层的这个位置有多少个数据能达到
}
}
int querry(int x)
{
int p = 0;
int res = 0;
for (int i = 29; i >= 0; i--)
{
int u = x >> i & 1;
int v = k >> i & 1;
if (!v)
res += cont[son[p][u^1]];
p = son[p][u ^ v];//这里的u^v同侧你可以把v=1带入,u值为多少结果就为多少
if (!p)
return res;
}
res += cont[p];
return res;
}
int main()
{
cin >> n >> k;
LL s = 0;
insert(s);
int res = 0;
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
s = s ^ x;
res += querry(s);
insert(s);
}
cout << res << endl;
return 0;
}