题目给定一个哈希表的长度和插入的元素,采用除留余数法作为哈希函数,使用平方探测法解决冲突,要求输出给定元素在哈希表中的插入位置。
输入第一行都包含两个正数:MSize 和 N 分别是用户定义的表大小和输入数字的数量。然后在下一行中给出 N 个不同的正整数。一行中的所有数字都用空格分隔。
在一行中打印输入数字的相应位置(索引从 0 开始)。一行中的所有数字均由空格分隔,并且行尾不得有多余的空格。如果无法插入数字,请打印-
。
由于给定的表长不会超过$10^4$,而且要求哈希表的实际表长是一个不小于给定表长的素数,可以用埃氏筛法先生成一张$10^5$的素数表,然后找出不小于给定表长的素数作为实际表长。通过将给定元素值对表长的余数作为在哈希表中的插入位置,如果出现冲突,采用平方探查法解决。平方探查法的具体过程是,假设给定元素值为 a,表长为 M,插入位置为$a%M$,假设$a%M$位置已有元素,即发生冲突,则查找$(a+1^2)%M$,$(a-1^2)%M$,$(a+2^2)%M$,$(a-2^2)%M$,$\cdots\cdots$,$(a+M^2)%M$,$(a-M^2)%M$ 直至查找到一个可进行插入的位置,否则当查找到$(a+M^2)%M$,$(a-M^2)%M$ 仍然不能插入则该元素插入失败。另外题目要求平方探测只需正向探测即可,也就是说,当发生冲突的时候,只需查找$(a+1^2)%M$,$(a+2^2)%M$,$\cdots\cdots$,$(a+M^2)%M$即可。
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
vector<gg> prime;
void getPrime(gg n = gg(1e5)) {
vector<bool> f(n + 5);
for (gg i = 2; i <= n; ++i)
if (not f[i]) { // i 没有被筛去
prime.push_back(i);
for (gg j = i + i; j <= n; j += i) //筛去 i 的所有倍数
f[j] = true;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
getPrime();
gg ni, mi, ai;
cin >> mi >> ni;
mi = *lower_bound(prime.begin(), prime.end(), mi);
vector<gg> table(mi);
for (gg i = 0; i < ni; ++i) {
cin >> ai;
gg k = ai % mi;
for (gg j = 1; j <= mi and table[k] != 0; ++j) {
k = (ai + j * j) % mi;
}
if (table[k] == 0) {
table[k] = ai;
cout << (i > 0 ? " " : "") << k;
} else {
cout << (i > 0 ? " " : "") << "-";
}
}
return 0;
}