この問題のタスクは簡単である:入力番号の位置をハッシュテーブルに異なる正の整数の配列を挿入し、出力します。ハッシュ関数は、と定義されるH(k個のE Y)= k個のE Yの%T S I Z E T S I Z eは、ハッシュテーブルの最大サイズです。(のみ正の増分で)プローブ次の衝突を解決するために使用されます。
テーブルサイズが素数であることを優れていることに注意してください。ユーザーが指定した最大サイズが素数でない場合は、テーブルのサイズは、ユーザによって与えられたサイズよりも大きい最小の素数であることを再定義する必要があります。
入力仕様:
各入力ファイルには、1つのテストケースが含まれています。各場合について、最初の行は、2つの正の数含まM S I Z E(≤104)及びN(≤ M S I Z E)は、それぞれ、ユーザー定義テーブルのサイズと、入力番号の数です。次いで、Nの異なる正の整数は、次の行に示されています。行のすべての数字は、スペースで区切られます。
出力仕様:
各テストケースのために、1つのラインの入力番号の対応する位置(0からインデックス開始)を印刷します。行のすべての数字は、スペースで区切られ、行の末尾に余分なスペースがあってはなりません。「 - 」の代わりにケースでは、印刷、番号を挿入することは不可能です。
サンプル入力:
4 4
10 6 4 15
サンプル出力:
0 1 4 -
思考
- 注目に場所の価値はその二次プロービングのための(唯一の正の増分を持つ)で平均二次検出方法、と、
a%size
実行競合が(a + step*step)%size, step=1,2,...
、問題の鍵検証し、適切なしようとするためにどのくらいのこの段階で嘘を取ることですsize-1
十分にインクルード - いいえ、厳密な証明ません:この超過と仮定し
size
、あなたが作るしたい場合がありstep = size + t
、(size + t)(size + t)
=size^2 + 2*size*t + t^2
のほかに、t^2
この項目他の%size
すべての後には0なくなって、バックに戻った(a+t*t)%size
開始点の始まり
コード
#include<bits/stdc++.h>
using namespace std;
bool used[10010] = {0};
bool is_prime(int x)
{
if(x <= 1) return false;
int up = (int)sqrt(x * 1.0);
for(int i=2;i<=up;i++)
if(x % i == 0)
return false;
return true;
} //判断素数的方法
int main()
{
int table_size, n;
cin >> table_size >> n;
if(!is_prime(table_size))
{
table_size++;
while(!is_prime(table_size))
table_size++;
} //检查表长是否为素数
int t;
for(int i=0;i<n;i++)
{
cin >> t;
int pos = t % table_size;
if(used[pos]) //位置被占用就用二次探测法(正向)
{
int step = 1;
int found = false;
for(;step<table_size;step++)
{
pos = (t + step * step) % table_size;
if(!used[pos])
{
found = true;
break;
}
}
if(found)
{
used[pos] = true;
if(i == 0)
cout << pos;
else
cout << " " << pos;
}else
{
if(i == 0)
cout << "-";
else
cout << " " << "-";
}
}else //如果位置没有被占用
{
used[pos] = true;
if(i == 0)
cout << pos;
else
cout << " " << pos;
}
}
return 0;
}
引用文
https://pintia.cn/problem-sets/994805342720868352/problems/994805389634158592