반응형
[Silver I] 곱셈 - 1629
성능 요약
메모리: 113112 KB, 시간: 108 ms
분류
분할 정복을 이용한 거듭제곱(exponentiation_by_squaring), 수학(math)
문제 설명
자연수 A를 B번 곱한 수를 알고 싶다. 단 구하려는 수가 매우 커질 수 있으므로 이를 C로 나눈 나머지를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 A, B, C가 빈 칸을 사이에 두고 순서대로 주어진다. A, B, C는 모두 2,147,483,647 이하의 자연수이다.
출력
첫째 줄에 A를 B번 곱한 수를 C로 나눈 나머지를 출력한다.
-첫 풀이
코린이 특징 => 시간 초과가 날 것을 알면서도 해보기
-분할정복 풀이
import sys
input = sys.stdin.readline
a, b, c = map(int,input().split())
def conquer(num, squared):
if squared == 1:
return num % c
elif squared % 2 == 0:
recursive = conquer(num, squared/2)
return recursive * recursive % c
else:
recursive = conquer(num, (squared-1)/2)
return recursive * recursive * num % c
print(conquer(a,b))
분할정복으로 복잡도를 줄여야 통과가 되는 문제다.
분할정복은 동일한 수식을 반으로 계속 쪼개어서 나눈 문제들을 재귀 방식을 통해 각각 해결한다.
해당 문제처럼 같은 수를 제곱하는 것은 분할정복 문제들의 가장 베이스적인 문제인 것 같다.
분할정복의 기본 알고리즘을 가장 잘 설명한 그림이 있어 이것을 참고하면 이해하기가 더 쉬울 것 같다.
처음에 아무 생각없이 c로 나눈 나머지를 출력할 때만 해서 시간 초과가 났었는데, return한 값이 결국 계산한 값이므로, 출력문(print)에 c로 나눈 나머지를 구해야 할 게 아니라, return 할 때마다 c로 나눈 나머지를 구해야 한다.
'알고리즘' 카테고리의 다른 글
[Gold V] 스타트링크 - 5014 (bfs) (1) | 2022.10.02 |
---|---|
[Silver I] 안전 영역 - 2468 (그래프 탐색) (2) | 2022.10.01 |
[Gold IV] 편의점 - 14221 (다익스트라) (1) | 2022.09.30 |
[Silver III] N과 M (2) - 15650 (백트래킹, 조합) (0) | 2022.09.30 |
[Gold IV] 불! - 4179 (BFS) (1) | 2022.09.29 |