Skip to content

Latest commit

 

History

History
60 lines (49 loc) · 2.6 KB

1078. Hashing.md

File metadata and controls

60 lines (49 loc) · 2.6 KB

pat 甲级 1078 Hashing

题意概述

题目给定一个哈希表的长度和插入的元素,采用除留余数法作为哈希函数,使用平方探测法解决冲突,要求输出给定元素在哈希表中的插入位置。

输入输出格式

输入第一行都包含两个正数:MSize 和 N 分别是用户定义的表大小和输入数字的数量。然后在下一行中给出 N 个不同的正整数。一行中的所有数字都用空格分隔。

在一行中打印输入数字的相应位置(索引从 0 开始)。一行中的所有数字均由空格分隔,并且行尾不得有多余的空格。如果无法插入数字,请打印-

数据规模

$$N<=MSize<=10^4$$

算法设计

由于给定的表长不会超过$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$即可。

C++代码

#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;
}