문제
트럭을 타고 이동하던 상근이는 경찰의 검문을 받게 되었다. 경찰은 상근이가 운반하던 화물을 하나하나 모두 확인할 것이기 때문에, 검문하는데 엄청나게 오랜 시간이 걸린다.
상근이는 시간을 때우기 위해서 수학 게임을 하기로 했다.
먼저 근처에 보이는 숫자 N개를 종이에 적는다. 그 다음, 종이에 적은 수를 M으로 나누었을 때, 나머지가 모두 같게 되는 M을 모두 찾으려고 한다. M은 1보다 커야 한다.
N개의 수가 주어졌을 때, 가능한 M을 모두 찾는 프로그램을 작성하시오.
입력
첫째 줄에 종이에 적은 수의 개수 N이 주어진다. (2 ≤ N ≤ 100)
다음 줄부터 N개 줄에는 종이에 적은 수가 하나씩 주어진다. 이 수는 모두 1보다 크거나 같고, 1,000,000,000보다 작거나 같은 자연수이다. 같은 수가 두 번 이상 주어지지 않는다.
항상 M이 하나 이상 존재하는 경우만 입력으로 주어진다.
5
5
17
23
14
833
출력
첫째 줄에 가능한 M을 공백으로 구분하여 모두 출력한다. 이때, M은 증가하는 순서이어야 한다.
30 36
접근 방식
구글링을 통해 풀이 방법을 참고했다
arr 배열에 적은 수를 담는다
arr[n] % M = arr[n] - (arr[n]/M ) * M 이다
M을 정답이라 했을 때 arr[n] % M 과 arr[n-1] % M 은 같다.
arr[n] - (arr[n]/M)M = arr[n-1] - (arr[n-1]/M)M 이고 정리하면 arr[n] - arr[n-1] = M * x 이다
이 때 x 는 상수이므로 생략한다
즉 arr[n] - arr[n-1]의 공약수는 M이고 최대 공약수의 약수는 모두 답이 될 수 있다
배열을 차례대로 올라가며 arr[n] - arr[n-1]의 모든 수에 대한 최대공약수를 구한 후 약수를 출력한다
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main_G5_2981 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int arr[] = new int[N];
for(int i=0;i<N;i++) {
arr[i] = Integer.parseInt(br.readLine());
}
Arrays.sort(arr);
int x = arr[1] - arr[0];
for(int i=2;i<N;i++) {
int a = arr[i] - arr[i-1];
if (a > x) x = gcd(a,x);
else x = gcd(x,a);
}
divisor(x);
}
public static int gcd(int a, int b) {
return b == 0 ? a : gcd(b,a%b);
}
public static void divisor(int x) {
StringBuilder sb = new StringBuilder();
for(int i=2;i<=x;i++) {
if(x % i == 0) {
sb.append(i).append(" ");
}
}
sb.setLength(sb.length()-1);
System.out.print(sb);
}
}