原题链接
题目大意
题目将会给你 n n n ( 1 ≤ n ≤ 1000000 ) (1\le n\le 1000000) (1≤n≤1000000)个数字组成的数列 a a a ( a i ≤ 2 30 ) (a_i\le 2^{30}) (ai≤230),和一个 k k k ( 1 ≤ k ≤ 2 30 ) (1\le k\le 2^{30}) (1≤k≤230),请输出有多少组 i , j i,j i,j满足 a i a_i ai x o r xor xor a j = k a_j=k aj=k。
解题思路
我们可以先来模拟一下:
(
11001011010010010111010010111
)
2
(11001011010010010111010010111)_2
(11001011010010010111010010111)2
x
o
r
xor
xor
?
=
(
11001011010010010111010100100
)
2
?=(11001011010010010111010100100)_2
?=(11001011010010010111010100100)2
想要得到"
?
?
?",我们可以先分析一下。众所周知,
a
a
a
x
o
r
xor
xor
k
=
b
k=b
k=b,那么,
a
a
a
x
o
r
xor
xor
b
=
k
b=k
b=k,也就是说,在题目中,如果
a
i
a_i
ai
x
o
r
xor
xor
a
j
=
k
a _j=k
aj=k,那么
a
i
=
a
j
a_i=a_j
ai=aj
x
o
r
xor
xor
k
k
k,所以,我们可以遍历每个i,如果
a
i
a_i
ai
x
o
r
xor
xor
a
j
=
k
a_j=k
aj=k,中的
j
j
j存在,那么
a
i
a_i
ai
x
o
r
xor
xor
k
k
k就必定存在与这个数列中。
优化
但是,你会发现,如果真的把数组开到 2 30 2^{30} 230的话,就会MLE(Memory Limit Exceeded),这时,我们便需要使用哈希算法进行优化。
哈希
题目给了你一个数列,我们想要把它们存下来,我们可以使用一个表,和一个质数,每个数都进行模运算,并将这个数存在下标为模运算结果的那个格子中(如果已经被占用,就往后推,直到找到第一个空的格子,再存进去)。
举个例子:
有10个数,分别是
1,3,5,6,7,9,10,12,13,20
选择的质数是17,那么我们来模拟一下存表的过程:
- 1 1 1 m o d mod mod 17 = 1 17=1 17=1
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- 3 3 3 m o d mod mod 17 17 17
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- 5 5 5 m o d mod mod 17 = 5 17=5 17=5
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- 6 6 6 m o d mod mod 17 = 6 17=6 17=6
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 5 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- 7 7 7 m o d mod mod 17 = 7 17=7 17=7
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 5 | 6 | 7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- 9 9 9 m o d mod mod 17 = 9 17=9 17=9
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 5 | 6 | 7 | 0 | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- 10 10 10 m o d mod mod 17 = 10 17=10 17=10
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 5 | 6 | 7 | 0 | 9 | 10 | 0 | 0 | 0 | 0 | 0 | 0 |
- 12 12 12 m o d mod mod 17 = 12 17=12 17=12
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 5 | 6 | 7 | 0 | 9 | 10 | 0 | 12 | 0 | 0 | 0 | 0 |
- 13 13 13 m o d mod mod 17 = 13 17=13 17=13
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 5 | 6 | 7 | 0 | 9 | 10 | 0 | 12 | 13 | 0 | 0 | 0 |
- 20 20 20 m o d mod mod 17 = 3 17=3 17=3
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 0 | 5 | 6 | 7 | 0 | 9 | 10 | 0 | 12 | 13 | 0 | 0 | 0 |
由于3的位置已经有了数字,所以,往后推,找到的第一给空的位置,也就是4,再存入数组:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | 20 | 5 | 6 | 7 | 0 | 9 | 10 | 0 | 12 | 13 | 0 | 0 | 0 |
代码实现
#include<bits/stdc++.h>
#define hash_number 2100001//大质数,存储时使用
using namespace std;
long long c[hash_number],a[hash_number],ans,n,k,t;
int hash1(long long x)
{
int i=x%hash_number;
while(c[i]&&a[i]!=x)//哈希查找
{
i++;//找到的位置存储再i中
if(i==hash_number) i=0;
}
return i;
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>t;
ans+=c[hash1((t^k))];
int t_to_hash=hash1(t);
a[t_to_hash]=t;
c[t_to_hash]++;
}
cout<<ans*2;//因为就像5 xor 4=1一样,应该统计两次(4 xor 5=1)
}
输入格式
第一行有两个整数,分别为
n
(
1
≤
n
≤
1000000
)
n(1\le n\le 1000000)
n(1≤n≤1000000)和
k
(
1
≤
k
≤
2
30
)
k(1\le k\le 2^{30})
k(1≤k≤230)
第二行有
n
n
n个数,分别为
a
1
a_1
a1至
a
n
a_n
an。
输出格式
只有一个数,为满足 a i a_i ai x o r xor xor a j = k a_j=k aj=k中 i i i 和 j j j 的组数。
样例
输入
5 1
1 4 2 2 5
输出
2
样例解释
两组分别为 ( a 2 , a 5 ) (a_2,a_5) (a2,a5)和 ( a 5 , a 2 ) (a_5,a_2) (a5,a2),也就是 4 4 4 x o r xor xor 5 = 1 5=1 5=1和 5 5 5 x o r xor xor 4 = 1 4=1 4=1。