pat 1078. Hashing (哈希表模拟)

本文详细介绍了如何使用筛法生成小于指定数值的最大素数,并结合二次探测法解决特定数学问题。通过实例分析,展示了算法的具体实现过程及应用效果。

本题中首先是要把M转化为大于等于N的最小素数M’

我用了筛法打素数表,我认为M<=10000不代表M‘也<=10000。比10000小的最大素数是9973,比10000大的最小素数是10007。

则筛法以2-103为宜(素数103^2>10007)而非2-97(素数97^2<9973)

打完表后就可以求得M’

然后再用二次探测法。注意二次探测法在不同的地方表述的细节有所不同,我在程序中是设(k+j^2)%M  k<M   没有k-j^2

程序如下:

#include<stdio.h>

const int MAX=10010;
int p[MAX];
int azu[MAX];
int num[MAX];
int array[27]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103};

void prime()
{
	int i,j;
	p[1]=1;
	for(i=0;i<27;i++)
		for(j=2;;j++)
			if(array[i]*j<MAX)
				p[array[i]*j]++;
			else
				break;
}

int main()
{
	prime();
	int m,n,x,i,y,j;
	scanf("%d %d",&m,&n);
    if(p[m])
	{
		while(p[m])
			m++;
	}
	for(i=0;i<n;i++)
	{
		scanf("%d",&x);
		y=x%m;
		j=0;
		while(azu[y])
		{
			if(j>=m) 
				break;
			j++;
			y=(x+j*j)%m;		
		}
		if(!azu[y])
		{
			azu[y]++;
			num[i]=y;
		}
		else
		{
			num[i]=-1;
		}
	}
    for(i=0;i<n;i++)
	{
		if(i)
			printf(" ");
		if(num[i]==-1)
			printf("-");
		else
			printf("%d",num[i]);
	}
    printf("\n");
	return 0;
}



### 替代方案或实现方式 `sun.misc.Hashing.randomHashSeed` 是一个内部类方法,主要用于生成随机的哈希种子值。然而,该方法在 JDK 8 中被移除,因为其多线程性能问题导致了潜在的性能瓶颈。以下是几种替代方案和实现方式: #### 1. 使用 `ThreadLocalRandom` `ThreadLocalRandom` 是 Java 提供的一个高性能随机数生成器,专为多线程环境设计。它可以作为 `randomHashSeed` 的替代方案,用于生成随机种子值。 ```java int randomHashSeed = ThreadLocalRandom.current().nextInt(); ``` 这种方法避免了多线程环境下的竞争问题,同时提供了高效的随机数生成能力[^6]。 #### 2. 自定义哈希种子生成逻辑 可以通过简单的数学运算生成一个伪随机的哈希种子值。例如,结合当前时间戳和线程 ID 来生成一个唯一的种子值: ```java int randomHashSeed = (int) (System.currentTimeMillis() ^ Thread.currentThread().getId()); ``` 这种方法虽然简单,但在某些场景下可能不够随机,因此需要根据具体需求进行调整[^7]。 #### 3. 使用 `SecureRandom` 如果对随机性要求较高,可以使用 `SecureRandom` 类生成更安全的随机数。尽管它的性能略低于 `ThreadLocalRandom`,但在安全性至关重要的场景中是一个不错的选择。 ```java SecureRandom secureRandom = new SecureRandom(); int randomHashSeed = secureRandom.nextInt(); ``` 这种方法适用于需要防止攻击者预测哈希种子值的场景[^8]。 #### 4. 模仿原始实现 如果必须模仿 `sun.misc.Hashing.randomHashSeed` 的行为,可以通过以下方式实现: ```java private static final AtomicInteger hashSeed = new AtomicInteger(0); public static int randomHashSeed() { return hashSeed.incrementAndGet(); } ``` 这种方式通过 `AtomicInteger` 确保了线程安全性,同时实现了类似的功能。需要注意的是,这种方法生成的种子值并非完全随机,而是递增的整数序列[^9]。 ### 注意事项 - 如果选择自定义实现,需确保生成的种子值分布均匀,以减少哈希碰撞的概率。 - 在高并发环境下,优先选择 `ThreadLocalRandom` 或 `SecureRandom`,以避免性能瓶颈。 - 如果仅需要一个简单的随机数生成器,可以使用 `Math.random()` 并将其转换为整数形式。 ```java int randomHashSeed = (int) (Math.random() * Integer.MAX_VALUE); ``` 这种方法简单易用,但随机性较差,不推荐在高并发或安全性要求较高的场景中使用[^10]。 ### 示例代码 以下是一个综合实现的示例,展示了如何在不同场景下选择合适的替代方案: ```java public class HashSeedGenerator { public static int generateThreadLocalRandomSeed() { return ThreadLocalRandom.current().nextInt(); } public static int generateSecureRandomSeed() { SecureRandom secureRandom = new SecureRandom(); return secureRandom.nextInt(); } public static int generateCustomSeed() { return (int) (System.currentTimeMillis() ^ Thread.currentThread().getId()); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值