题目来源
题目描述
农夫约翰有
N
(
1
≤
N
≤
5000
)
N(1 \le N \le 5000)
N(1≤N≤5000)头奶牛,每头奶牛都有一个唯一的不同于其它奶牛的编号
s
i
s_i
si,所有的奶牛都睡在一个有
K
K
K个厩的谷仓中,厩的编号为0到
K
−
1
K−1
K−1。每头奶牛都知道自己该睡在哪一个厩中,因为约翰教会了它们做除法,
S
i
S_i
Si
m
o
d
mod
mod
K
K
K的值就是第
i
i
i头奶年所睡的厩的编号。
给出一组奶牛的编号,确定最小的
K
K
K 使得没有2头或2头以上的奶牛睡在同一厩中。
输入格式
第一行一个正整数 N N N,第2到 N + 1 N+1 N+1行每行一个整数表示一头奶牛的编号。
输出格式
一个整数,表示要求的最小的 K K K,对所有的测试数据这样的 K K K是一定存在的。
输入输出样例
输入
5
4
6
9
10
13
输出
8
解题思路
题目的意思要求我们找出一个最小的K值,使得K模上奶牛所有的编号得到的厩的编号两两不相等。一开始我用暴力for循环的方法,但是只得到80分,显然超时了。所以对于数论问题,一定有公式能方便我们求解。在这道题,我们用到了以下的思想:
若
a
≡
b
(
m
o
d
K
)
a \equiv b \pmod K
a≡b(modK),即K模a,b的值相等的条件存在(a,b分别是奶牛的编号),则K能整除|a-b|(由题意知,a,b两两不相等)。
证明:假设
a
=
K
∗
n
+
a
1
a=K*n+a1
a=K∗n+a1,
b
=
K
∗
m
+
b
1
b=K*m+b1
b=K∗m+b1,其中n,a1,m,b1都为整数,由条件可知,余数a1=b1。所以a-b=K(n-m)。所以,我们要新建一个数组,对编号之间两两相减的值作为索引,并打上标记,再由小到大找那些没有打上标记的索引并输出;
但是,这样处理完之后,还不是正确。因为我们还没有考虑到|a-b|的因子的情况:若K整除|a-b|,K的因子也能整除|a-b|,但这些因子我们可能没有标记。所以,我们在取得一个未被标记的索引之后,我们还要遍历
K
∗
i
K*i
K∗i,i为大于1的正整数。如果遍历结果都没有标记,那么输出最小值K。
AC代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int N = 0;
Scanner scan = new Scanner(System.in);
N = scan.nextInt();
//记录1到N头奶牛的编号
int Cow[] = new int[N];
int Num[] = new int[1000001];
for(int i = 0 ;i < N;i++) {
Cow[i] = scan.nextInt();
}
for(int i = 0 ;i < N-1;i++) {
for(int j = i+1 ;j < N;j++) {
Num[Math.abs(Cow[i]-Cow[j])]=1;
}
}
boolean judge = true;
//因为厩的数量显然比奶牛的数量多,所以从N开始找;因为余数代表厩的编号肯定小于N,而且厩的编号和奶牛编号一一对应
for(int K = N;K < 1000001;K++) {
if(Num[K] == 0) {
for(int j = K ; j < 1000001;j+=K) {
if(Num[K] == 1) {
judge = false;
break;
}
}
if(judge) {
System.out.println(K);
break;
}
}
}
scan.close();
}
}
Ps:觉得不错就点个赞吧,期待你的三连!