The task of this problem is simple: insert a sequence of distinct positive integers into a hash table, and output the positions of the input numbers. The hash function is defined to be H(key)=key%TSize where TSize is the maximum size of the hash table. Quadratic probing (with positive increments only) is used to solve the collisions.
Note that the table size is better to be prime. If the maximum size given by the user is not prime, you must re-define the table size to be the smallest prime number which is larger than the size given by the user.
Input Specification:
Each input file contains one test case. For each case, the first line contains two positive numbers: MSize (≤104) and N (≤MSize) which are the user-defined table size and the number of input numbers, respectively. Then N distinct positive integers are given in the next line. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the corresponding positions (index starts from 0) of the input numbers in one line. All the numbers in a line are separated by a space, and there must be no extra space at the end of the line. In case it is impossible to insert the number, print "-" instead.
Sample Input:
4 4
10 6 4 15
Sample Output:
0 1 4 -
-------------------------------这是题目和解题的分割线-------------------------------
先来回顾一下素数判断吧~
①最常见的方法,复杂度O(sqrt(n))
bool isPrime(int n)
{
if(n<=1) return false; //1既不是素数也不是合数
//如果是合数,因子一个在sqr的左边,一个在右边,判断其中一边即可
int sqr = (int)sqrt(n*1.0); //sqrt的参数要求是浮点数 *1.0
for(int i=2;i<=sqr;i++)
if(n%i==0) return false;
return true;
}
枚举部分的复杂度是O(n),所以这个方法在判断素数的总函数里复杂度是O(n*sqrt(n))。
当n不超过10^5时,是不会超时的。
②如果遇到n很大的情况,可以用素数筛法,O(nloglogn)。
举个例子,求1-10的所有素数。
1. 2是素数(唯一需要事先确定),因此筛去所有2的倍数,即4、6、8、10
2. 3没有被前面的步骤筛去,因此3是素数,筛去所有3的倍数,即6、9
3. 4已经在1中被筛去,因此4不是素数
4. 5没有被前面的步骤筛去,因此5是素数,筛去所有5的倍数,即10
..............以此类推
由此可见,当从小到大到达某数x时,如果x没有被前面步骤的数字筛去,那么a一定是素数。
void findPrime()
{
for(int i=2;i<maxN;i++) //maxN是表长
{
//初始化a[i]为false,如果i为素数,a[i] = true
if(a[i]==false)
{
//把素数i存在数组里
prime[count++] = i;
//在剩余的数字里遍历,筛去该素数的倍数,置为true
for(int j=i+1;j<maxN;j+=i)
a[j] = true;
}
}
}
好啦回到题目本身!
有几个点需要注意一下,
①哈希表的冲突处理 Quadratic probing ,中文名是平方探查法,即当H(a)发生冲突时,令a等于a+1^2、a-1^2、a+2^2、
a-2^2...的顺序调整a的值,直到不冲突或者到达边界为止。题目说明(with positive increments only),只要往正向解决冲突,
即a+1^2、a+2^2...
②测试点1答案错误,可能是错把1当质数了。
②测试点3运行超时,是因为在冲突处理的过程中,找到位置时没有及时中断这个循环。
③测试点2、3都答案错误,是数组开的太小了,我最早开的10005就不够,至少10007才行。
#include<cstdio>
#include<math.h>
int isPrime(int x)
{
if(x<=1) return 0; //1不是素数
int sqr = (int)sqrt(x*1.0);
for(int i=2;i<=sqr;i++)
if(x%i==0) return 0;
return 1;
}
int main()
{
//数组至少10007以上
int i,n,m,a[10010],hash[10010] = {};
scanf("%d%d",&m,&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
while(!isPrime(m)) m++;
for(i=0;i<n;i++)
{
int flag = 0;
if(!hash[a[i]%m])
{
hash[a[i]%m] = 1;
a[i] = a[i]%m;
}
else
{
//平方探查法
for(int j=1;j<=m;j++)
{
if(!hash[(a[i]+j*j)%m])
{
hash[(a[i]+j*j)%m] = 1;
a[i] = (a[i]+j*j)%m;
flag = 1;
break; //及时中断
}
}
if(!flag) a[i] = -1;
}
}
for(i=0;i<n;i++)
{
if(a[i]!=-1) printf("%d",a[i]);
else printf("-");
if(i!=n-1) printf(" ");
}
}