[02981] 검문

문제

트럭을 타고 이동하던 상근이는 경찰의 검문을 받게 되었다. 경찰은 상근이가 운반하던 화물을 하나하나 모두 확인할 것이기 때문에, 검문하는데 엄청나게 오랜 시간이 걸린다.

상근이는 시간을 때우기 위해서 수학 게임을 하기로 했다.

먼저 근처에 보이는 숫자 N개를 종이에 적는다. 그 다음, 종이에 적은 수를 M으로 나누었을 때, 나머지가 모두 같게 되는 M을 모두 찾으려고 한다. M은 1보다 커야 한다.

N개의 수가 주어졌을 때, 가능한 M을 모두 찾는 프로그램을 작성하시오.

입력

첫째 줄에 종이에 적은 수의 개수 N이 주어진다. (2 ≤ N ≤ 100)

다음 줄부터 N개 줄에는 종이에 적은 수가 하나씩 주어진다. 이 수는 모두 1보다 크거나 같고, 1,000,000,000보다 작거나 같은 자연수이다. 같은 수가 두 번 이상 주어지지 않는다.

항상 M이 하나 이상 존재하는 경우만 입력으로 주어진다.

출력

첫째 줄에 가능한 M을 공백으로 구분하여 모두 출력한다. 이때, M은 증가하는 순서이어야 한다.

코드

#include <iostream>
#include <algorithm>
using namespace std;

/* 조건 */
#define MAX_N 100
#define MAX_NUM 1000000000

/* 변수 */
int N;
int arr[MAX_N + 1];
int gcd;

/* 함수 */
int GCD(int a, int b) {
    if(a % b == 0) return b;
    return GCD(b, a%b);
}

void printDivisors(int n) {
    for(int i = 2; i < n / 2; i++) {
        if(n % i == 0)
            cout << i << ' ';
    }
    if(n % 2 == 0) cout << n/2 << ' ';
    cout << n << '\n';
}

int main() {
    /* 입력 */
    cin >> N;
    for(int i = 0; i < N; i++) {
        cin >> arr[i];
    }
    sort(arr, arr+N);

    /* 풀이 */
    gcd = arr[1] - arr[0];
    for(int i = 2; i < N; i++) {
        if(arr[i] - arr[0] % gcd == 0) continue;
        gcd = GCD(arr[i] - arr[0], gcd);
    }

    /* 출력 */
    printDivisors(gcd);
}

풀이과정

함수

  • GCD(a, b)
    • 유클리드 호제법을 이용해 최대공약수 GCD(Greatest Common Divisor)를 구하는 함수
    • a와 b의 최대공약수를 출력함
  • printDivisor(n)
    • n의 약수를 출력한다.
    • 1부터 n까지 출력하면 시간초과가 되므로 n/2까지만 출력했다.
    • 최적의 방법은 sqrt(n)까지만 확인하는 것이 최적이지만 그러려면 숫자들을 저장해둬야 하기 때문에 n/2까지로 하고, n이 2의 배수라면 n/2를 따로 출력하도록 했다.

원리

나머지를 같게 하는 제수(除數: 나누는 수) M이 있을 때,
arr[i], 임의의 수 A과 나머지 r에 대하여
아래와 같은 식이 성립한다.

arr[0] = A * M + r
...
arr[i-1] = A` * M + r
arr[i] = A`` * M + r

또한 위의 식을 서로 빼주면 아래와 같이 된다.

arr[i] - arr[i-1] = (A - A`) * M

위는 서로를 빼주면 나머지가 0인 제수 M이 존재한다.
즉, M은 서로를 빼준 수의 공약수이며,
모든 M을 구하는 법은 빼준 숫자들의 최대공약수를 구하고, 그 수의 약수들이다.

따라서 /* 풀이 */ 부분의 for 반복문에서
arr[i]에서 arr[0]을 빼준 숫자들의 최대공약수를 구해주고,

printDivisor(n) 함수를 이용해 출력해주었다.

출처

백준 [02981] 검문
https://www.acmicpc.net/problem/2981

profile
Handong Global Univ.

0개의 댓글