4. POSTECH Computer Algorithm Team
A) 2 ~ X-1중에 나눠 떨어지는 수가 있다면 소수가 아니고, 없다면 소수입니다.
- 하지만 단순히 소수 판별을 위해서 2부터 X-1까지 돌아볼 필요는 없습니다.
- 나누어 떨어진다는 것은 X = p * q (p,q > 1인 자연수)로 나타낼 수 있다는 뜻이고,
- 항상 min(p,q) <= sqrt(X)를 만족합니다.
- 즉, 단순한 X의 소수 판별을 위해서는 sqrt(X)까지만 돌아보면 됩니다.
• sqrt(X) 는 X의 제곱근입니다.
소수 판별
소수
5. POSTECH Computer Algorithm Team
- 그렇다면 소인수 분해는 어떨까요?
- 소인수 분해는 한 합성수를 소수들의 곱으로 나타내는 것입니다.
- 방금 설명한 소수 판별법을 응용하여, 아래와 같이 sqrt(X)까지 돌아보며 나누어지는 수로 최대한 나누면 됩니다.
for(int div = 2; div <= sqrt(X); div++) {
while(n % div == 0) {
n /= div
arr[div]++;
}
}
Q) 하지만 위의 코딩대로 한다면 소수가 아닌 숫자로도 나눠지지는 않을까요?
소인수 분해
소수
6. POSTECH Computer Algorithm Team
A) 아닙니다. 만약 div가 합성수라면, 이미 X는 div의 소인수로 나누어 졌기 때문에 합성수인 div로는 나누어지지
않습니다.
- 물론 위 코딩은 소수를 미리 구하기 귀찮아 저런 방식으로 한 것이고, 소수를 미리 구해둔다면 조금 더 빠르게
소인수 분해를 할 수 있습니다.(물론 소수를 구하는 과정을 포함한다면 빠르지 않습니다.)
소인수 분해
소수
7. POSTECH Computer Algorithm Team
- 저희는 지금까지 X가 소수인지 아닌지 판별하거나, X를 소인수 분해하는 방법을 알아보았습니다.
- 그렇다면 X이하의 모든 소수를 구하고 싶을 때는 어떻게 하면 좋을까요?
- 바로 떠오르는 것은 3~X까지 돌아보며 소수판별법을 사용하는 것입니다.
- 그 방법은 O(X*sqrt(X))의 시간복잡도를 가지게 됩니다.
- 좀 더 빠른 방법을 소개하겠습니다.
에라토스테네스의 체
소수
8. POSTECH Computer Algorithm Team
- 소수 판별에서 i로 나누어 떨어지는지 매번 확인했던
작업을 i로 나누어 떨어지는 X이하의 수를 소수후보에
서 제거함으로써 한번에 처리한 모습입니다.
- 에라토스테네스의 체는 O(XloglogX)의 시간 복잡도를
보입니다.
- 시간 복잡도에 대한 증명은
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
#Algorithm_complexity 에서 볼 수 있습니다. 전 모르
겠어요.
에라토스테네스의 체
소수
9. POSTECH Computer Algorithm Team
- Euclidean algorithm은 유클리드 호제법이라고도 합니다.(기록이 남은 인류 최초의 알고리즘이라고 합니다.)
- 두 앙의 정수(혹은 다항식)의 최대공약수를 빠르게 구하는 알고리즘 인데, 아래 굵은 표시가 주요 내용입니다.
- 두 정수 a,b(a > b)의 공약수 집합은 *p-q, q의 공약수 집합과 같습니다.
- 따라서 gcd(p,q) = gcd(p-q ,q)와 같습니다. (gcd = Greatest Common divisor, 최대공약수)
- 이를 반복하여 두 수를 입력 받아 최대공약수를 리턴하는 함수를 만들 수 있습니다.
* (p,q 의 공약수 g가 있으면, p = Pg , q = Qg로 나타낼 수 있고, p-q = (P-Q)g이므로 g는 p-q의 공약수이다.)
유클리드 알고리즘
유클리드
10. POSTECH Computer Algorithm Team
int gcd(int p, int q) {
if(p<q) swap(p,q);
if(q == 0) return p;
return gcd(p-q,q);
}
- 하지만 위 코드는 p가 크고 q가 작으면 불필요한 연산을 너무 많이 진행합니다.
(e.g. gcd(100000,6) = gcd(999994,6) = gcd(999988,6) …………)
- 불필요한 연산을 없애기 위해 이를 발전시키면,
결론
유클리드
11. POSTECH Computer Algorithm Team
int gcd(int p, int q) {
if(q==0) return p;
return gcd(q,p%q);
}
- 이와 같은 함수가 됩니다.
- 혹시 gcd(p,q) = gcd(p-q,q)는 알겠는데 gcd(p,q) = gcd(q,p%q)는 왜 성립하는지 모르겠다면 뒤의
두 슬라이드를 봐주세용
결론
유클리드
12. POSTECH Computer Algorithm Team
- 두 양의 정수 a,b (b > a)에 대하여 b = aq + r (r > a >= 0, 즉 r = b%a)라 하면 a,b의 최대 공약수는 a,r의 최
대 공약수와 같습니다.
- 즉, gcd(a,b) = gcd(a,b%a) 입니다.
- 증명과정은 다음과 같습니다.
- r = b%a라고 하면
- gcd(a,b) = G라고 하면, 서로소인 정수 A,B에 대해 a = GA, b = GB가 성립합니다.
- 이를 b = aq + r에 대입하면 GB = GA*q + r
- r = G(B-Aq)이므로 G는 r과 a의 공약수 입니다.
- 이제 일단 G가 r과 a가 공약수 인 것을 알았으니, 최대공약수인지 확인해보겠습니다.
유클리드 알고리즘의 증명2
유클리드
13. POSTECH Computer Algorithm Team
- r = G(B-Aq)이므로,
- gcd(A,B−Aq) = 1를 만족한다면 G가 최대공약수이겠죠.
- gcd(A,B−Aq) = m이라고 하면, 서로소인 정수 k,l에 대해 A = mk, B-Aq = ml이 성립합니다.
- B-Aq = ml -> B = ml+Aq = ml + mkq = m(l+kq)입니다.
- 즉, m은 A와 B의 공약수인데, A와 B는 서로소이므로 m=1입니다.
- 그러므로 A와 B−Aq는 서로소이고, gcd(a,b) = gcd(a,b%a)이 증명됩니다.
유클리드 알고리즘의 증명2
유클리드
14. POSTECH Computer Algorithm Team
- 나머지 연산에 대해 다음과 같은 식들이 성립합니다.
• (a+b)%M = ((a%M) + (b%M))%M
• (a-b)%M = ((a%M) - (b%M) + M)%M
• (a*b)%M = ((a%M) * (b%M))%M
- 위와 같은 성질들은 주로 문제에서 다루는 수가 너무 커질 때 사용합니다.
나머지 연산
Modular arithmetic
15. POSTECH Computer Algorithm Team
- 확장 유클리드 알고리즘
유틀리드 알고리즘은 gcd(p,q)를 수행하며 p,q를 서로 빼는 과정을 반복하기 때문에, gcd(p,q) = ap+bq로 나타낼 수
있습니다. 유클리드 알고리즘에 적절하게 코드를 추가하면 a와 ,b도 반환하도록 할 수 있습니다.
- 중국인 나머지 정리
연립 합동식의 유일한 해를 찾는 정리입니다.
- 모듈라 연산의 나눗셈
모듈라 연산에서 나눗셈은 a/b에서 b로 나누는 대신 b의 곱셈 역원을 곱해줍니다.
추가 읽을거리
와! 확장!
16. POSTECH Computer Algorithm Team
https://www.acmicpc.net/problem/3474
https://algospot.com/judge/problem/read/PASS486
https://algospot.com/judge/problem/read/POTION
https://www.acmicpc.net/problem/6588
Problems