문제
자연수 A를 B번 곱한 수를 알고 싶다. 단 구하려는 수가 매우 커질 수 있으므로 이를 C로 나눈 나머지를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 A, B, C가 빈 칸을 사이에 두고 순서대로 주어진다. A, B, C는 모두 2,147,483,647 이하의 자연수이다.3
출력
첫째 줄에 A를 B번 곱한 수를 C로 나눈 나머지를 출력한다.
나의 풀이
이 문제는 분할 정복 알고리즘을 사용해서 해결하는 거듭제곱을 진행하는 방법을 묻는 문제이다. 분할 정복 알고리즘에 대한 설명은 아래의 게시글에서 확인할 수 있다.
일단 바로 거듭제곱을 구할 수 있는 코드를 보겠다.
fun pow(A: Int, B: Int): Int{
return pow(A, B)
}
pow 함수를 사용해서 A를 B번 거듭제곱한 결과를 반환해주는 간단한 코드다. 이 코드의 시간 복잡도는 O(N)번이 된다. 지금 A, B의 크기가 Int의 최대값 임으로 이 방식으로는 시간 초과가 발생하고 만다. 그러니까 이제 분할 정복 알고리즘을 이용해서 거듭제곱을 진행하면 된다.
분할 정복 알고리즘을 거듭제곱으로 진행하는 방법을 알아보겠다.
7^11을 계산한다고 생각해보자. 지수법칙에 의거해 7^11을 7^5 * 7^5 * 7로 나눌 수 있다. 이렇게 되면 구해야할 양이 한번에 줄어든다. 이런 방식으로 계속해서 분할하면 O(logN)의 시간복잡도로 우리가 원하는 값을 구할 수 있다.
정답 코드는 아래와 같다.
fun main() = with(System.`in`.bufferedReader()) {
var (A, B, C) = readLine().split(" ").map { it.toLong() }
var result = 1L
while (B > 0) {
if (B % 2 == 1L)
result = result * A % C
A = A * A % C
B /= 2
}
println(result)
}
'백준 > 기타' 카테고리의 다른 글
2470번: 두 용액 - Kotlin, Java (투 포인터) (0) | 2023.09.14 |
---|---|
1717번: 집합의 표현 - Kotlin (Union - Find) (0) | 2023.09.10 |
9953번: 문자열 폭발 - Kotlin (스택) (0) | 2023.05.16 |
1644번: 소수의 연속합 - Kotlin (투 포인터, 에라토스테네스의 체) (0) | 2023.03.28 |
2003번: 부분합 - Kotlin (투포인터) (0) | 2023.03.14 |