1 条题解
-
0
自动搬运
来自洛谷,原作者为

chen_zhe
Aya 敲可爱的~搬运于
2025-08-24 21:18:04,当前版本为作者最后更新于2025-03-11 11:26:43,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
欢迎报名洛谷网校,期待和大家一起进步!
本题考察 map 的使用。
题目询问有多少个数对满足 ,直接枚举 ,判断其是否是 的幂次,则时间复杂度是 或者 的( 表示 的值域,是否有 取决于是否使用位运算
x & (x - 1)判断正整数 是否是 的幂次),只能通过 的数据。不妨移项,有 。接着我们枚举 和 ,即可计算出 。接着我们判断 是否有出现过即可。这一步就需要使用
map。具体而言,使用map <int, int> m存储 这个值出现的次数。这样,我们只需统计 出现了多少次,将这个次数累加进答案中即可。接下来演示一个经典的错误写法:
for (int i = 1; i <= n; i++) { m[a[i]]--; for (int j = 0; j <= 30; j++) ans += m[(1 << j) - a[i]]; }在这份代码中确实是在枚举 和 ,得知 的出现次数并且加到答案,同时也通过
m[a[i]]--的方式避免重复统计,但是这一份代码提交只能获得部分分数。这是因为若是直接访问map下标,此时如果 不存在值,则会新建一个下标 ,值为 。这样一来,这个map容器中就会存在 个元素( 在本题中为 ),单次访问时间复杂度为 ,总复杂度为 ,无法通过本题。一个更好的做法是,首先使用
m.count()函数,判断这个下标是否在map中出现过。若没出现过就不管,出现过了再计算。这样可以避免反复地新建下标。由于count函数单次是 的,因此时间复杂度为 ,可以通过本题。参考代码:
for (int i = 1; i <= n; i++) { m[a[i]]--; for (int j = 0; j <= 30; j++) { if (m.count((1 << j) - a[i])) ans += m[(1 << j) - a[i]]; } }
- 1
信息
- ID
- 11676
- 时间
- 500ms
- 内存
- 512MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者