약수와 배수란?
\(a\)를 \(b\)로 나누어 떨어지면(\(a \% b == 0\)), \(b\)는 \(a\)의 약수, \(a\)는 \(b\)의
배수입니다. 이 관계와 최대공약수(GCD)·최소공배수(LCM)는 정수론 문제의 기본기입니다.
1. 약수 구하기
\(N\)의 약수를 찾으려면 1부터 \(N\)까지 나눠 보면 되지만, 더 빠른 방법이 있습니다.
int n; cin >> n;
for (int i = 1; i <= n; i++)
if (n % i == 0) cout << i << ' '; // i가 약수
약수는 항상 쌍으로 나옵니다. \(i\)가 약수면 \(N/i\)도 약수죠. 그래서 \(\sqrt{N}\)까지만
보면 됩니다(아래 구현 단원에서 다룸).
2. 최대공약수 (GCD)
두 수의 공통 약수 중 가장 큰 것입니다. 유클리드 호제법으로 빠르게 구합니다.
\(\gcd(a, b) = \gcd(b, a \bmod b)\), 그리고 \(\gcd(a, 0) = a\)
"큰 수를 작은 수로 나눈 나머지로 바꾸기"를 나머지가 0이 될 때까지 반복합니다.
gcd(24, 18)
= gcd(18, 24%18=6)
= gcd(6, 18%6=0)
= 6
이 방법은 \(O(\log)\) 수준으로 매우 빠릅니다. 1부터 다 나눠 보는 것과 비교가 안 됩니다.
3. 최소공배수 (LCM)
두 수의 공통 배수 중 가장 작은 것. GCD를 이용한 공식이 있습니다.
$$ \text{lcm}(a, b) = \frac{a \times b}{\gcd(a, b)} $$
long long lcm = (long long)a / gcd(a, b) * b; // 곱 전에 나눠서 오버플로 방지
\(a \times b\)가 클 수 있으니, 먼저 나누고 곱하는 순서가 안전합니다.
4. 자주 쓰는 곳
- 분수 약분(분자·분모를 GCD로 나눔).
- "동시에 출발한 두 신호가 다시 만나는 시각" → LCM.
- "여러 개를 똑같이 나눠 담는 최대 크기" → GCD.
복잡도
- 약수 나열(단순): \(O(N)\), \(\sqrt N\) 기법: \(O(\sqrt N)\).
- 유클리드 호제법: \(O(\log \min(a,b))\).
정리
- 약수/배수는
% == 0으로 판정. - GCD는 유클리드 호제법: \(\gcd(a,b)=\gcd(b, a\%b)\).
- LCM은 \(a \times b / \gcd(a,b)\) — 곱 전에 나누기.
- 약분, 주기, 균등 분배 문제의 기본 도구.