题目

思路
代码流程
① 预处理素数:用埃氏筛法生成足够大范围内的所有素数(按升序排列),为后续查找做准备;
② 缩小查找范围:基于鸽巢原理,直接定位到第一个≥n/2 的素数(sz<n/2 时必然不满足要求,无需校验)
③ 校验合法素数:从上述素数开始,按升序逐个验证:
- 统计每个素数 sz 下,数组元素哈希值的出现次数(计数原理);
- 找到第一个满足 "所有哈希值计数≤2" 的素数,即为答案。
核心依据
- 选素数:素数作为哈希表大小能让哈希值分布更均匀,减少规律性冲突;
- 范围优化:鸽巢原理(n 个元素放入 sz 个位置,sz<n/2 则必存在≥3 个元素映射到同一位置);
- 合法性校验:计数原理(统计哈希值出现次数,量化冲突次数)。
代码
cpp
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define MAX_SZ 10000
int T,n,cnt=0,a[1000];
int hash[MAX_SZ],primes[MAX_SZ];
bool st[MAX_SZ+1]={false};
void sieve(){
for(int i=2;i<=MAX_SZ;i++){
if(st[i]) continue;
primes[cnt++]=i;
for(int j=i*i;j<=MAX_SZ;j+=i){
st[j]=true;
}
}
}
bool check(int n,int sz){
memset(hash, 0, sizeof(int) * (sz+1));
int i,k;
for(i=0;i<n;i++){
k=a[i]%sz;
if(hash[k]++>1) return false;
}
return true;
}
int main() {
int i;
sieve();
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (i = 0; i < n; i++) scanf("%d", &a[i]);
for(i=0;primes[i]<(n>>1);i++);
for(;!check(n,primes[i]);i++);
printf("%d\n",primes[i]);
}
return 0;
}