Algorithm
[1629] 곱셈 - Python
갬쿠
2023. 2. 21. 20:41
/* 문제 */
자연수 A를 B번 곱한 수를 알고 싶다. 단 구하려는 수가 매우 커질 수 있으므로 이를 C로 나눈 나머지를 구하는 프로그램을 작성하시오.
분할 정복 문제다.
어떤 수의 거듭제곱을 단순히 모두 곱해서 구한다면 시간 복잡도는 O(n)이지만 분할 정복을 이용해 구하면 O(log n)으로 해결할 수 있다.
a의 b제곱은
- b가 짝수일 경우 a^b = a^(b/2) * a^(b/2)
- b가 홀수일 경우 a^b = a^((b-1)/2) * a^((b-1)/2) * a
로 나타낼 수 있다. 따라서 재귀를 이용해 b가 1이 될 때까지 문제를 쪼개서 풀도록 구현했다.
또한 이 문제는 단순히 거듭제곱을 구하는 것이 아니라 나머지를 구하는 문제다.
- a = cx + y (a를 c로 나눈 나머지는 y)
라고 한다면
- a^2 = (cx)^2 + 2cxy + y^2 = Qc + y^2
이므로, 나머지만 거듭제곱하여 모듈러 연산을 적용해도 a 전체를 거듭제곱하여 계산하는 것과 같은 결과가 나올 것이다. 따라서 a를 계속해서 거듭제곱하지 않고 매번 모듈러 연산을 적용해 계산의 비용을 줄였다.
# 정답 코드
a, b, c = map(int, input().split())
def sol(a, b, c):
if b == 1:
return a % c
res = sol(a, b//2, c)
if b % 2 == 0:
return (res*res) % c
else:
return (res*res*a) % c
print(sol(a, b, c))
** 끝나고 찾아보니 모듈러 연산의 분배법칙을 미리 알고 있었다면 생각을 한 단계 더 할 필요가 없었을 것 같다 ^^
/* 나머지 분배 법칙 */
(A*B) % C = (A%C) * (B%C) % C
문제 풀이 중에 충분히 생각할 수 있는 내용이지만 시간 절약을 위해 기억해 놓는게 좋겠다.
728x90