Developing Myself Everyday
 

1629번: 곱셈

첫째 줄에 A, B, C가 빈 칸을 사이에 두고 순서대로 주어진다. A, B, C는 모두 2,147,483,647 이하의 자연수이다.

www.acmicpc.net

 

문제

자연수 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)
}
profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!