원리
문제를 부분문제로 분할하고, 분할된 문제들을 해결후에 다시 조합해나가서 결과를 도출하는 알고리즘
https://namu.wiki/w/%EB%B6%84%ED%95%A0%20%EC%A0%95%EB%B3%B5%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98
분할 정복 알고리즘 - 나무위키
분할 정복(Divide and Conquer)은 여러 알고리즘의 기본이 되는 해결방법으로, 기본적으로는 엄청나게 크고 방대한 문제를 조금씩 조금씩 나눠가면서 용이하게 풀 수 있는 문제 단위로 나눈 다음 그
namu.wiki
예시
https://www.acmicpc.net/problem/1629
위 문제를 풀려고 A**B%C라고 작성하면 시간초과가 뜬다.
왜냐하면 A**B는 A를 B번 곱하기 때문에 시간복잡도가 O(N)이 된다.
이를 해결하기 위해 2가지 법칙을 사용해야한다.
지수법칙
나머지 분배법칙
(A + B) % C = ((A % C) + (B % C)) % C
(A * B) % C = ((A % C) * (B % C)) % C
(A - B) % C = ((A % C) - (B % C) + C) % C
|
나머지 분배법칙을 이용해서 위 문제를 분할 정복 알고리즘을 적용할 수 있다.
나머지 분배법칙으로 입력 예시의 10 11 12를 풀자면,
10**11%12 = ((10**5%12) * (10**5%12)) % 12 |
이렇게 쪼갤 수 있다.
10**5또한 (10**2)*(10**2)*10으로 쪼개고 10**2또한 쪼개고 나면 가장 작은 부분문제가 완성된다.
이를 해결한 후 다시 합하면 원래의 답을 찾을 수 있게된다.
시간복잡도는 트리형태로 풀었기 때문에 O(logN)이 된다.
이를 코드로 작성하면
def sol(A, B, C):
if B==1:
return A%C
res = sol(A, B//2, C)
if B%2:
return (res*res*A)%C
else:
return (res*res)%C
a,b,c = map(int,input().split())
print(sol(a,b,c))
이렇게 적을 수 있다.
sol(A, B//2, C)를 계속 반복하기 때문에 res로 묶었다.
참조
https://hbj0209.tistory.com/43
[Algorithm] 분할정복을 이용한 거듭제곱
# 분할정복을 이용한 거듭제곱 - C**n연산은 x를 n번 곱하므로 O(N)이지만, 이 방법을 사용하면 O(logN)에 거듭제곱 값을 구할 수 있다. - 아래 코드에서 fpow함수가 그 방법이다. - n이 1이면 그냥 C의 1
hbj0209.tistory.com
'백준 > 이론_python' 카테고리의 다른 글
문자열 뒤집기 python (0) | 2023.04.11 |
---|---|
나머지 분배법칙(모듈러 연산) (0) | 2023.02.11 |
백준의 long과 int의 차이 (0) | 2023.02.11 |
비트 마스킹 C++ (0) | 2023.01.17 |
Union & Find 알고리즘 (0) | 2022.12.10 |
댓글