에듀테크 프로젝트 대시보드
빠른 거듭제곱 (Fast Exponentiation)
an 을 구하려면 a × a × … × a 처럼 곱셈을 n − 1번 하면 된다.
n이 10억쯤 되면 이 방법은 사실상 끝나지 않는다. 빠른 거듭제곱(square-and-multiply,
분할 정복 거듭제곱)은 지수를 절반으로 접어가며 곱셈 횟수를 약 log₂n번으로 줄인다 —
n = 10억이면 60번 이하. 핵심 아이디어 두 줄:
다르게 보면, 지수 n을 2진수로 쓰고 a¹, a², a⁴, a⁸, … (계속 제곱)을 만들어 두었다가,
비트가 1인 자리의 값만 골라 곱하면 된다. RSA·디피–헬만·해시·모듈러 역원 등
큰 수의 거듭제곱이 필요한 거의 모든 곳에서 쓰인다.
n = (2) ·
낮은 자리(오른쪽)부터 훑는다. 매 단계: 비트가 1이면 현재
base 를 결과에 곱하고,
그 다음 base 를 제곱한다.
| 단계 | 비트 | base = a2ᵏ | 동작 | result |
|---|
암호에서는 an mod m 이 필요하다. an 을 다 계산하면 자릿수가 수백만 개가 되지만,
매 곱셈마다 곧바로 mod 를 취하면 수가 항상 m보다 작게 유지된다. 곱하기 전에 접든, 곱한 뒤에 접든
결과가 같다는 모듈러 산술의 성질 덕분이다: (x·y) mod m = ((x mod m)·(y mod m)) mod m.
| 비트 | base mod m | result mod m |
|---|
cd mod N, d와 N이 2048비트 → square-and-multiply로 약 3000번 곱셈이면 끝.2²⁰⁴⁸ 번 — 우주가 끝나도 안 끝난다.# 반복(iterative) — 지수의 비트를 낮은 자리부터 def power(a, n, m=None): result = 1 base = a if m is None else a % m while n > 0: if n & 1: # 현재 최하위 비트가 1이면 result *= base if m: result %= m base *= base # base 를 제곱: a^1 -> a^2 -> a^4 ... if m: base %= m n >>= 1 # 지수를 오른쪽으로 한 칸 (n //= 2) return result # 재귀(divide and conquer) def power_rec(a, n): if n == 0: return 1 half = power_rec(a, n // 2) return half * half * (a if n & 1 else 1)
pow(a, n, m), Java BigInteger.modPow 가 내부에서 바로 이 알고리즘을 쓴다.| 단순 반복 | 빠른 거듭제곱 | |
|---|---|---|
| 곱셈 횟수 | n − 1 | ≤ 2·⌊log₂n⌋ |
| 시간 복잡도 | O(n) | O(log n) |
| 추가 메모리 | O(1) | O(1) 반복 / O(log n) 재귀 |
| n = 2³⁰ 일 때 | ≈ 10.7억 번 | ≈ 45 번 |
| 쓰이는 곳 | 작은 지수 | RSA, 디피–헬만, 해시, 행렬 거듭제곱, 조합론 mod p |