1078 Hashing (25 分)
題目傳送門:1078 Hashing (25 分)
一、題目大意
將給定長度爲n的數組放到長度爲M的哈希表中,如果M不是素數,則將M往後擴大到M後面的第一個素數。
在哈希時如果衝突,則二次探測再散列。剛開始沒注意這一句:Quadratic probing (with positive increments only) is used to solve the collisions.,以至於最後一組數據一直過不了。
二、解題思路
將M擴增到大於等於的M的最小素數不難,難點是不知道什麼是哈希表二次探測再散列,我百度後才知道,其實就是當將key往哈希表中存的時候,當發現key%M這一位已經存放了別的數了,那再放key就會產生衝突,那麼我們該怎麼解決衝突呢,就是二次探測,就是依次看(key±i^2)%M是否存放數,i是從1到M-1,如果遇到一個未存放數的哈希位置,我們就把key放到放到(key±i^2)%M這個位置上即可。
三、AC代碼
#include<bits/stdc++.h>
using namespace std;
vector<int>P{2};
void init(int n){//滾動數組產生素數表
for(int i = P.back()+1; i <= n; i+=2){
bool f = true;
for(auto j: P){
if(i % j == 0){
f = false;
break;
}
}
if(f){
P.push_back(i);
}
}
}
int main(){
int M, N;
cin >> M >> N;
if(M == 1)M++;
init(M);
if(P.back() != M){
for(int i = M+1; ; i++){
bool f = true;
for(auto j: P){
if(i % j == 0){
f = false;
break;
}
}
if(f){
P.push_back(i);
break;
}
}
M = P.back();
}
vector<int>v(N), hash(M);
for(int i = 0; i < N; i++){
int x;
cin >> x;
if(hash[x%M] == 0){// 原位存入
hash[x%M] = x;
v[i] = x % M;
}else{// 衝突,二次探測
bool f = true;
for(int j = 1; j < M; j++){
int y = x + j*j;
if(hash[y%M] == 0){
hash[y%M] = x;
v[i] = y%M;
f = false;
break;
}
}
if(f)// 二次探測後依舊衝突無法存放
v[i] = -1;
}
}
for(int i = 0; i < N; i++){
if(i){
if(v[i]==-1){
cout << " -";
}else{
cout << " " << v[i];
}
}else{
if(v[i]==-1){
cout << "-";
}else{
cout << v[i];
}
}
}
cout << endl;
}