引
考虑如下这个问题:
给定 n 个非负整数 a1,a2,…,an,你需要回答 q 次询问,每次询问查询 x 是否在这 n 个非负整数里面出现。
数据范围:1≤n,q≤106,0≤ai<264.
结合所学知识,不难想到以下两种做法:
- 方法一:将所有数储存在一个链表里面,每次询问的时候从头到尾枚举里面的每一个元素,看看是否和查询的数 x 相同。这个方法的时间复杂度为 O(nq),无法解决较大的数据规模。
- 方法二:定义数组 occ[val] 表示 val 是否出现过,每次询问 x 时,访问 occ[x] 可以直接得到所需的信息。该算法的时间复杂度为 O(n+q),然而,若 a 的值域过大(比如达到了 1018 的量级),就需要声明一个长度为 1018 的数组,将需要消耗 1018×4 B≈3.6×106 TB 的空间,显然无法接受。
如果保证数列 a 里的每一个元素都在值域内 均匀随机 地生成,该问题可以被一个较为巧妙的做法解决。
观察这 n 个数的最后四位数码,容易发现,若 a 里的每个元素都随机生成,那么 ai 的最后四位数码在 [0,104) 中也应该是均匀分布的,如果把 a 中所有最后四位全是 0 的存成一个链表,那么这个链表的长度期望为 104n。对于其他最后四位的组合也是同理。
当查询一个值 x 是否在 a 中出现时,也就不需要像方法一里面那样枚举 n 个数,而是只需要看跟 x 最后四位相同的数即可。
题面
给定 n 个非负整数 a1,a2,…,an,你需要回答 q 次询问,每次询问查询 x 是否在这 n 个非负整数里面出现。
若 x 出现,输出 x 在数列最后一次出现的位置,否则输出 0。