MingyuPark

[백준 1629] 곱셈 본문

Algorithm

[백준 1629] 곱셈

MingyuPark 2023. 2. 16. 15:37

문제 

https://www.acmicpc.net/problem/1629

 

1629번: 곱셈

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

www.acmicpc.net


아이디어

f(n)xn을 계산하기 위해 필요한 최소 계산 횟수라고 하자.

 

216을 계산하기 위해 필요한 최소 계산 횟수를 구해보자. 

  • 직접 계산하면 2를 16번 곱해야 하기 때문에 16번의 계산이 필요하다. 

이 경우 n이 2,147,483,647이 되면 계산 횟수가 너무 많아진다. 이럴 때 분할 정복을 이용한다. 

 

f(16)

= f(8)+1 : 216=2828이기 때문  

 

 

f(8)

= f(4)+1 : 28=2424이기 때문  

 

 

f(4)

= f(2)+1 : 24=2222이기 때문  

 

f(2)=2

 

결론적으로 

f(16)=f(8)+1=(f(4)+1)+1=((f(2)+1)+1)+1=((2+1)+1)+1=5가 된다. 

 

이렇게 분할 정복을 이용해서 계산 횟수를 줄여야 한다. 

 

그리고, 나머지에 대한 분배법칙을 확인해보자. 

a=k1m+l1,b=k2m+l2라고 하면 a%m=l1,b%m=l2이다.

그리고, a+b=(k1+k2)m+(l1+l2)가 된다. 

(k1+k2)mm으로 나누어 떨어지고, (l1+l2)m보다 큰 경우 나머지는 (l1+l2)%m 이기 때문에

(a+b)%m=(l1+l2)%m이 된다. (뺄셈도 똑같이 진행하면 됨)

 

곱셈도 마찬가지인데, ab=(k1k2)m2+k1l2m+k2l1m+(l1l2)가 된다. 

k1k2m2, k1l2m, k2l1m  은 m으로 나누어 떨어지고, (l1l2)m보다 큰 경우 나머지는 (l1l2)%m 이기 때문에

ab%m=(l1l2)%m이 된다.

 

이를 코드로 구현하면 다음과 같다. 


Solution

a, b, c = map(int, input().split())

def f(a, b) : 
    if b == 1 : 
        return a % c
    else : 
        rec = f(a, b//2)
        if b % 2 == 0 : 
            return rec**2%c
        else : 
            return a*rec*rec%c

print(f(a, b))

 

 

'Algorithm' 카테고리의 다른 글

[백준 11660] 구간 합 구하기 5  (0) 2023.02.16
[백준 10830] 행렬 제곱  (0) 2023.02.16
[백준 11478] 서로 다른 부분 문자열의 개수  (0) 2023.02.16
[백준 1932] 정수 삼각형  (0) 2023.02.04
[백준 16953] A → B  (0) 2023.02.04