logo

연속제곱법 증명 📂정수론

연속제곱법 증명

알고리즘

자연수 a,k,ma,k,m 에 대해 bak(modm)b \equiv a^{k} \pmod{m} 를 다음과 같이 계산할 수 있다.


Step 1. kk 의 이진법 전개

ui=0u_{i} = 0 혹은 ui=1u_{i} = 1 에 대해 다음과 같이 나타낸다. k=i=0rui2i=u0+2u1++2rur k = \sum_{i=0}^{r} u_{i} 2^{i} = u_{0} + 2 u_{1} + \cdots + 2^r u_{r}


Step 2.

aA0(modm)a2(a1)2A02A1(modm)a4(a2)2A12A2(modm)a8(a4)2A22A3(modm) \begin{align*} a & & & \equiv A_{0} \pmod{m} \\ a^{2} & \equiv ( a^1 )^2 & \equiv A_{0}^2 & \equiv A_{1} \pmod{m} \\ a^{4} & \equiv ( a^2 )^2 & \equiv A_{1}^2 & \equiv A_{2} \pmod{m} \\ a^{8} & \equiv ( a^4 )^2 & \equiv A_{2}^2 & \equiv A_{3} \pmod{m} \\ & & & \vdots \end{align*} 위와 같이 a2r(a2r1)2Ar12Ar(modm)a^{2^{r}} \equiv ( a^{2^{r-1}} )^2 \equiv A_{r-1}^2 \equiv A_{r} \pmod{m} 를 계산한다.


Step 3.

A0u0A1u1ArurA_{0}^{u_{0}} \cdot A_{1}^{u_{1}} \cdot \cdots A_{r}^{u_{r}} 을 계산하면 다음을 얻는다. akA0u0A1u1Arur(modm) a^{k} \equiv A_{0}^{u_{0}} \cdot A_{1}^{u_{1}} \cdot \cdots A_{r}^{u_{r}} \pmod{m}

설명

컴퓨터의 발전으로 거듭제곱의 계산도 빠르게 할 수 있는 시대가 왔지만 인간은 만족을 모른다. 연속제곱법은 모듈러 연산에 무지막지하게 큰 숫자를 직접 구하지 않고도 그 답을 내주는 방법이다. 한번 제곱할때마다 (modm)\pmod{m} 으로 나눠주기 때문에 수가 mm 이하로 떨어져서 계산량이 줄어드는 것이다.

예제

예를 들어 7327(mod853)7^{327} \pmod{853} 을 구한다고 해보자. 73277^{327} 에 상용로그를 취하면 327log73270.8450=276.315327 \log 7 \approx 327 \cdot 0.8450 = 276.315 이므로 자릿수만 무려 277277 인 큰 수다. 정직하게 다 곱해서 나눗셈을 하기엔 너무 크니까 위의 알고리즘을 사용해보자. 일단 위의 알고리즘대로 327327 를 이진법 전개하면 다음과 같다. 327=256+64+4+2+1=28+26+22+21+20 327 = 256 + 64 + 4 +2 +1 = 2^{8} + 2^{6} + 2^2 + 2^1 + 2^0 Step 2대로 계산해보면 777(mod853)72(71)27249(mod853)74(72)24922401695(mod853)78(74)26952227(mod853)716(78)22272349(mod853)732(716)23492675(mod853)764(732)26752123(mod853)7128(764)21232628(mod853)7256(7128)26282298(mod853) \begin{align*} 7 & & \equiv 7 & \equiv 7 \pmod{853} \\ 7^{2} & \equiv ( 7^1 )^2 & \equiv 7^2 & \equiv 49 \pmod{853} \\ 7^{4} & \equiv ( 7^2 )^2 & \equiv 49^2 & \equiv 2401 \equiv 695 \pmod{853} \\ 7^{8} & \equiv ( 7^4 )^2 & \equiv 695^2 & \equiv 227 \pmod{853} \\ 7^{16} & \equiv ( 7^8 )^2 & \equiv 227^2 & \equiv 349 \pmod{853} \\ 7^{32} & \equiv ( 7^{16} )^2 & \equiv 349^2 & \equiv 675 \pmod{853} \\ 7^{64} & \equiv ( 7^{32} )^2 & \equiv 675^2 & \equiv 123 \pmod{853} \\ 7^{128} & \equiv ( 7^{64} )^2 & \equiv 123^2 & \equiv 628 \pmod{853} \\ 7^{256} & \equiv ( 7^{128} )^2 & \equiv 628^2 & \equiv 298 \pmod{853} \end{align*} 따라서 7327=7256764747271=298123695497286(mod853) 7^{327} = 7^{256} \cdot 7^{64} \cdot 7^{4} \cdot 7^{2} \cdot 7^{1} = 298 \cdot 123 \cdot 695 \cdot 49 \cdot 7 \equiv 286 \pmod{853} 이다. 이 방법도 힘들다고 느낄 수는 있겠지만, 그냥 327327 번을 일일이 곱하는 것에 비하면 아주 해봄직한 계산량이다.

증명

ak=au0+2u1++2rur=au0a2u1a2rurA0u0A1u1Arur(modm) \begin{align*} a^{k} =& a^{u_{0} + 2u_{1} + \cdots + 2^r u_{r} } \\ =& a^{u_{0}} a^{ 2u_{1} } \cdots a^{ 2^r u_{r} } \\ \equiv & A_{0}^{u_{0}} A_{1}^{u_{1}} \cdots A_{r}^{u_{r}} \pmod{m} \end{align*}

코드

아래는 연속제곱법으로 7327(mod853)7^{327} \pmod{853} 구하는 예제 코드로, R 언어로 작성되었다. 참고로 power 옵션은 음의 정수에도 대응되며, mod가 소수라면 power=-1을 입력함으로써 주어진 base의 곱셈에 대한 역원을 구할 수 있다.

FPM<-function(base,power,mod) #It is equal to (base^power)%%mod
{
  i<-0
  if (power<0) {
    while((base*i)%%mod != 1) {i=i+1}
    base<-i
    power<-(-power)}
  
  if (power==0) {return(1)}
  if (power==1) {return(base%%mod)}
  
  n<-0
  while(power>=2^n) {n=n+1}
  
  A<-rep(1,n)
  A[1]=base
  
  for(i in 1:(n-1)) {A[i+1]=(A[i]^2)%%mod}
  
  for(i in n:1) {
    if(power>=2^(i-1)) {power=power-2^(i-1)}
    else {A[i]=1} }
  
  for(i in 2:n) {A[1]=(A[1]*A[i])%%mod}
  
  return(A[1])
}
 
FPM(7,327,853)
FPM(7,-1,11)