题目描述
Venn有一个数列\(a_1,a_2,...,a_n\).有一天,BLUESKY007拿来了一个正整数\(X\)。Venn是一个特别喜欢异或(xor)运算的孩子,她也很喜欢BLUESKY007。于是,Venn就想知道,自己能找到多少对数(i,j)能够满足\(a_i \ xor \ a_j = X\). 两个数对\((i_1,j_1)\)与\((i_2,j_2)\)不同,当且仅当\(i_1 \neq i_2\)或者\(j_1 \neq j_2\)。
思路
这题暴力肯定要超时(50分)。固要用二分查找。
解析
这道题除了用上面的算法外,还有一个比较容易理解的方法,详见代码。
这道题首先需要知道一个性质: 如果 a ^ b = c
, 则
a ^ c = b
, b ^ c = a
.
不知道这个性质, 这道题西奈.
当你有一个有序数组, 应该怎样快速的判断这个数组里有多少个值等于 x 的数呢?
eg. a[] = {1, 2, 4, 5, 5, 6, 6, 10, 23, 74};
且数组长度
n = 10, 你要查询这个数组里出现了多少次 x = 5.
先求出第一个大于 x 的数的地址, 再求出第一个大于等于 x 的数的地址,
两者相减就是答案. 即: 1
ans = std::upper_bound(a, a+n, x) - std::lower_bound(a, a+n, x);
std::upper_bound
和 std::lower_bound
不是返回地址吗?
Answer: 1
2
3 (std::upper_bound(a, a+n, x) - a) - (std::lower_bound(a, a+n, x) - a)
=std::upper_bound(a, a+n, x) - a - std::lower_bound(a, a+n, x) + a // 两个 a 抵消, 得
=std::upper_bound(a, a+n, x) - std::lower_bound(a, a+n, x)
时间复杂度为 \(O(log n) \ll O(n)\).
不知道这个性质, 这道题西奈.
这道题还有一个比较坑的, 就是时限太小. 所以你必须手写排序或者手写二分以提高效率.
不知道这一点, 这道题西奈.
1 |
|