개념

자연수 NN을 나누어떨어지게 하는 자연수가 NN의 약수입니다. ii가 약수이면 N/iN/i도 약수이며 두 수의 곱은 NN입니다.

약수 쌍

두 약수가 모두 N\sqrt N보다 크면 곱이 NN보다 커집니다. 따라서 11부터 N\sqrt N까지 검사하면 모든 약수 쌍을 찾을 수 있습니다.

1212의 약수 쌍은 (1,12),(2,6),(3,4)(1,12),(2,6),(3,4)입니다. 3636의 (6,6)(6,6)처럼 두 값이 같으면 한 번만 기록합니다. 오름차순 출력이 필요하면 모은 약수를 정렬합니다.

예를 들어 1212에서 1,2,31,2,3을 검사하면 반대쪽 약수 12,6,412,6,4도 함께 얻습니다. 44를 다시 검사하면 이미 얻은 (3,4)(3,4) 쌍을 반대로 확인하게 됩니다. 작은 쪽만 검사해도 모든 약수를 얻는 이유입니다. 약수 목록을 직접 나열해야 하는 문제에 이 방법을 사용합니다.

복잡도

자연수를 NN, 약수 개수를 DD라고 합니다.

연산시간복잡도공간복잡도
약수 탐색·정렬O(N+Dlog⁡D)O(\sqrt N+D\log D)결과 저장 O(D)O(D)

예제

문제

양의 정수의 모든 약수를 오름차순으로 출력하여라.

입력

첫째 줄에 양의 정수 NN이 주어진다. 1≤N≤9 9991\le N\le9\,999이다.

출력

약수를 한 줄에 공백으로 구분하여 출력한다.

예제 입력

12

예제 출력

1 2 3 4 6 12

예제 코드

C++20

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

vector<int> v;

int main() {
    int n, i;

    cin >> n;
    for (i = 1; i <= n / i; ++i) {
        if (n % i == 0) {
            v.push_back(i);
            if (i != n / i) v.push_back(n / i);
        }
    }
    sort(v.begin(), v.end());

    for (int x : v) {
        cout << x << ' ';
    }
    cout << '\n';
}