[编程题] 异或
时间限制:1秒
空间限制:32768K
给定整数m以及n各数字A1,A2,..An,将数列A中所有元素两两异或,共能得到n(n-1)/2个结果,请求出这些结果中大于m的有多少个。
输入描述:
第一行包含两个整数n,m. 第二行给出n个整数A1,A2,...,An。 数据范围 对于30%的数据,1 <= n, m <= 1000 对于100%的数据,1 <= n, m, Ai <= 10^5
输出描述:
输出仅包括一行,即所求的答案
输入例子1:
3 10 6 5 10
输出例子1:
2
思路:trie入门题,对每个数的二进制由高位到低位建立字典树,然后贪心地选择就OK。
# include <bits/stdc++.h>
using namespace std;
const int N = 1e5+30;
int a[N], cnt=0, n, m;
struct node{
int Next[2], sum;
}node[N*40];
long long cal(int x){
long long res = 0;
int pos = 0;
for(int i=30; i>=0; --i){
int tar = (m>>i)&1;
int cur = (x>>i)&1;
if(tar == 1)
pos = node[pos].Next[cur^1];
else{
res += node[node[pos].Next[cur^1]].sum;
pos = node[pos].Next[cur];
}
if(pos == 0) break;
}
return res;
}
void update(int x){
int pos = 0;
for(int i=30; i>=0; --i){
int bit = (x>>i)&1;
if(node[pos].Next[bit] == 0) node[pos].Next[bit] = ++cnt;
pos = node[pos].Next[bit];
++node[pos].sum;
}
}
int main(){
long long ans = 0;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
for(int i=1; i<=n; ++i){
ans += cal(a[i]);
update(a[i]);
}
printf("%lld\n",ans);
return 0;
}