2的幂的哈希表

64位的各位对应值的哈希表,这是一个为了能够有效单独处理每一位所对应的一个数据。由于一共有64位,二进制各位模64,从第7位开始就全为0了,故首先从65看,而65不冲突的个数仅为12个,66不冲突的个数仅为11个。但计算到67时,会发现,刚好所有二进制单位上的值模67全部无冲突。即有64个不重复的数字。这些数字可以构建一个2的幂的哈希表,使得所有查询,修改,删除全为 O ( 1 ) O(1) O(1)
因此采用 hash ( n ) = n  mod  67 \text{hash}(n)=n\ \text{mod}\ 67 hash(n)=n mod 67 即可构建无冲突的二的幂的哈希表。对一些进制函数的处理非常有用,二进制在各种组合dfs中总会碰到的,可以考虑这样的hashmap。
示例













或许你以为到这就完了,但实际上,稍微想想,能找到一些数论的关系出来。

原根定义,若 g i ≡ 1 ( mod  n ) g^i\equiv1\left(\text{mod}\ n\right) gi1(mod n)的最小正整数 i = φ ( n ) i=\varphi(n) i=φ(n) g g g n n n的原根。
很显然,哈希表的函数要的是2作为哪个大于等于最大长度的数的原根。如这里是找到大于等于64的原根。设 m m m为定义域长度,即最高要达到的 a i a^i ai i i i的最大值为 m m m。则 φ ( n ) ≥ m \varphi(n)\ge m φ(n)m n n n a a a的原根。

最好的结果是直接考虑 n n n为素数的情况, n n n是素数下。 φ ( n ) = n − 1 ≥ m \varphi(n)=n-1\ge m φ(n)=n1m,需从 m + 1 m+1 m+1开始考虑。考虑大于 m m m的素数,检测其是否具备 2 2 2作为其原根的特性。不过光这个也都无法有固定公式,因为2是否是无穷多个素数的原根的问题本来就未被证明的,它来自于埃米尔阿廷猜想。当然不会有固定的公式。但是就一般的ACM题或者工程需要,不超过64的范围内都没有什么特别的需要处理的。

可以用Mathematica来查询:

SelectFirst[Select[Prime[Range[k]], # > m &], PrimitiveRoot[#] == 2 &]

表示大于m的在前k个素数中找到原根为2的n。这个数就是构建哈希表模的数。输入k=100和m=64可得67恰为答案。
对于m=128来说,k取100可得131为哈希表长。

mk
32100037
64100067
1281000131
2561000269
5121000523
102410001061

还有一种方法查询,但是是大概率不会查到最小一个满足的:

FindInstance[Prime[n] > m && PrimitiveRoot[Prime[n]] == 2, n, Integers, k]

其中获得的是第n个素数的n,需要自行选取内部的n。当m特别大时采用。
这里讨论的东西可以完全扩展到其他底数的单幂值的哈希表,不只是2还可以有3,5等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值