概率 - 哈希杂谈
简介
我们最常接触的哈希通常是对字符串任意子串的哈希,并且被定义为 ,其中 是自选的常数。
然而经过了一系列题目之后,我发现对集合的哈希也是有很多种的,并且有多种的实现方式。
随机权之(异或)和
如果我们不需要对集合进行任何的操作,只需要判断是否相等,通常这种实现是比较好的。
设集合中的元素是 的整数,初始化 为 的数,并定义集合 的哈希值 。
若集合 ,不妨设存在 且 (如果 就反过来),那么 的概率就是下面这个东西的概率:
由于式子右侧与 完全无关,根据随机初始化的独立性,这个概率就是 。
如果整个程序运行过程中,我们需要进行 次比较,那么碰撞的概率就会有一个 的上界,取 这个值通常是可以接受的。
通常来讲,上面 也可以定义为 ,碰撞概率分析同理。
幂之和
如果我们需要对集合进行一个整体加数的操作,赋随机权就没那么好用了。
设集合中的元素是 的整数,并定义集合 的哈希值 ,这里 是自选的常数。
这里的概率分析就比较玄学了,在出题人不知道你的 的情况下,如果你选的 为 的原根,应当就很难卡掉。
这样定义的好处是,如果你需要整体 ,那么 的变化就是 。
[CF1418G] Three Occurrences
固定一个 ,我们考虑有多少的 是合法的。
对于恰好三次这个限制,通常可以认为是一个套路,我们通过两个约束保证这一点:
- 所有数出现次数是 的倍数。
- 所有数出现次数不超过 。
对于第二个约束,满足条件的所有 显然是在以 为右端点的一个连续区间内的,并且这个区间的边界是可以通过双指针来更新的。
因此我们只需要解决第一个问题。也就是说,我们希望如果一个数出现了三次,那么它对这个集合的哈希值的贡献就为 。
考虑对一个数 按照出现次数模 分别赋 ,其中 。
这样一来,只要出现次数是三的倍数,它的贡献就为 。根据上文的概率分析,当出现次数不是 的倍数时,哈希值为 的概率为 。
又因为这里只考虑连续的区间,至多只有 个区间存在出现次数不为 的倍数的元素,也就是隐性进行了 次比较,根据上文的分析,这个错误概率是比较低的。
[2026 HDU多校 4] Rare Game
的部分比较简单:设 表示 的方案数。枚举最后一段,那么转移就是 ,其中 表示 中每一个数的出现次数都是 。
考虑使用哈希处理这个比较难搞的条件。同上,我们也是通过两个约束保证合法性:
- 所有数出现次数是 的倍数。
- 所有数的出现次数不超过 。
现在和上面那个题目基本上就一样了。
[ABC238G] Cubic?
和上面不一样的是,这里要求的不是每个质因数出现的次数恰好为 ,而是 的倍数,所以都不需要双指针了。
[HDU8113] 炼金术士的配方
不同于上面的题目,我们不再是需要查询多少个区间的哈希值为 的情况,所以之前按照出现次数模 的方法加法哈希就不太行了,因为我们无法保证奇数次出现和偶数次出现贡献的东西相等,然后它们加到一起又贡献 。
但是这个东西恰好能用异或的方法表示,这也通常被称为异或哈希。
[JLCPC2025] 另一个回文问题
本质上,本题是询问一个区间内奇数位置构成的多重集是否与偶数位置相同,并且要支持区间加。
只要使用幂之和哈希就可以轻松维护了,并且我们这里可以令位置 维护的值是 ,这样只需要查询区间和是否为 即可。
[ICPC2025 Hong Kong R] DFS Order - Extra Stage
考虑一个 DFS 序对于树结构的限制是什么。
一个显然的必要条件是,如果 是一个 DFS 序,那么对任意一个节点 的所有后代都必须在 中紧连在 后面形成一个连续的区间。
这是否充分呢?也就是说,如果对任意一个节点 ,它的所有后代都在 中紧连在 后面形成一个连续的区间,那么 就是一个合法的 DFS 序吗?
这是对的。考虑 的所有儿子 ,将它们按照 中出现的先后顺序进行 DFS,通过数学归纳法可以证明它能得到 。
给每一个节点 开一个哈希表 ,用 表示 这个集合在 中,作为紧连在 后面的一个连续区间出现的次数。当且仅当 时, 可以作为 的后代集合。
由于 要求 在 中就出现,所以对后续新出现的集合种类,我们可以不把它们加入哈希表,这样空间保持 ,尽管时间是 。
引用一句我比较喜欢的话,但是忘记出处了: 是一个尴尬的数字,这意味着你的时间复杂度可以是 ,但是空间复杂度却通常不能是 。
这里集合就可以用随机权哈希的方法去处理。
进一步的,如何计数?看到 ,考虑 的区间 。
在处理完所有限制后,我们只对 进行 DP。
设 表示区间 能够形成的所有树的种类,如果 不是 的一个合法后代集合,那么 ;否则,那么我们枚举第一个子树的管辖范围进行转移:
其中 表示将 划分为若干个区间能够形成的森林的总数。因为枚举第一个子树后,后面的显然是一个森林,所以需要这样设计。
那么它的转移如下:
可以看出, 是依赖 的,但是 不会依赖到当前层的 ,所以这个转移是不会相互依赖的。