Skip to content

Commit 3196fb6

Browse files
committed
docs: 모듈러 역원에 대한 내용 보충
1 parent 69d7e4b commit 3196fb6

File tree

1 file changed

+98
-8
lines changed

1 file changed

+98
-8
lines changed

_posts/2024-03-06-modular-arithmetic.md

Lines changed: 98 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,120 @@ $(a−b)\,mod\;m=[(a\,mod\;m)−(b\,mod\;m)]\,mod\;m$
3939

4040
#### 곱셈
4141

42-
$(a*b)\,mod\;m=[(a\,mod\;m)*(b\,mod\;m)]\,mod\;m$
42+
$(a \times b)\,mod\;m=[(a\,mod\;m)\times(b\,mod\;m)]\,mod\;m$
4343

44-
### 거듭제곱
44+
#### 거듭제곱
4545

4646
$(aᵇ)\,mod\;m=((a\,mod\;m)ᵇ)\,mod\;m$
4747

48-
### 모듈러 역원을 이용한 나눗셈
48+
#### 모듈러 역원을 이용한 나눗셈
4949

50-
모듈러 연산에서는 $(a/b)\,mod\;m$을 직접 구할 수 없습니다. 대신 b의 `곱셈 역원(Multiplicative inverse)`를 곱하는 방식으로 계산할 수 있습니다.
50+
모듈러 연산에서는 $(a/b)\,mod\;m$을 직접 구할 수 없습니다. 대신 b의 `모듈러 역원(Modular inverse)`를 곱하는 방식으로 계산할 수 있습니다.
5151

52-
$(a/b)\,mod\;m=(a*b⁻¹)\,mod\;m$
52+
$(a/b)\,mod\;m=(a\times b⁻¹)\,mod\;m$
5353

5454
<blockquote class="prompt-info"><p><strong><u>Info.</u></strong> <br />
55-
<b>모듈러 역원(Modular Inverse)</b>: 정수 a와 m에 대해 <b>(a * x) mod m = 1</b>을 만족하는 정수 x를 a의 모듈러 역원이라고 합니다. 예를 들어 정수 a가 3이고 m이 11일 때 (3 * 4) mod 11 = 1이므로 3의 모듈러 역원은 4입니다. <br />
55+
<b>모듈러 역원(Modular inverse)</b>: 정수 a와 m에 대해 <b>(a * x) mod m = 1</b>을 만족하는 정수 x를 a의 모듈러 역원이라고 합니다. 예를 들어 정수 a가 3이고 m이 11일 때 (3 × 4) mod 11 = 1이므로 3의 모듈러 역원은 4입니다. <br />
5656
</p></blockquote>
5757

5858
<blockquote class="prompt-info"><p><strong><u>Info.</u></strong> <br />
5959
b의 곱셈 역원은 항상 존재하는 것이 아니라, <b>b와 m이 서로소</b>일 때만 존재합니다. 다만 출제되는 대부분의 알고리즘 문제에서는 m이 <b>소수</b>인 경우가 많습니다.</p></blockquote>
6060

61-
모듈러 역원은 주로 TODO
61+
모듈러 역원을 구하는 방법으로는 여러 가지가 있습니다.
62+
63+
<br />
64+
65+
<b>1. 페르마의 소정리</b>
66+
67+
만약 m이 소수인 경우, 아래의 `페르마의 소정리`를 활용하여 모듈러 역원을 쉽게 구할 수 있습니다.
68+
69+
$(a⁻¹)\,mod\;m = (aᵐ⁻²)\,mod\;m$
70+
71+
숫자 3의 모듈러 역원을 구하면 다음과 같이 4임을 확인할 수 있습니다.
72+
73+
$3⁻¹\,mod\;11 = 3¹¹⁻²\,mod\;11=3⁹\,mod\;11=19683\,mod\;11=4$
74+
75+
<br />
76+
77+
<b>2. 확장 유클리드 알고리즘(Extended Euclidean Algorithm)</b>
78+
79+
확장 유클리드 알고리즘(Extended Euclidean Algorithm)을 활용하여 모듈러 역원을 구할 수 있습니다.
80+
81+
$a\times x+m\times y=gcd(a,m)$ 에서 <b>gcd가 1일 때(=a와 m이 서로소)</b>의 x 값이 a의 역원입니다.
82+
83+
$3x+11y=1$
84+
85+
$x=-7,\,y=2$
86+
87+
$(-7)\,mod\;11=4\,mod\;11=4$
88+
89+
```javascript
90+
const modInverse = (a, m) => {
91+
if (m === 1) {
92+
return 0;
93+
}
94+
95+
const m0 = m;
96+
let x0 = 0;
97+
let x1 = 1;
98+
99+
while (a > 1) {
100+
const q = Math.floor(a / m);
101+
[a, m] = [m, a % m];
102+
[x0, x1] = [x1 - q * x0, x0];
103+
}
104+
105+
if (x1 < 0) {
106+
x1 += m0;
107+
}
108+
return x1;
109+
};
110+
111+
console.log(modInverse(3, 11)); // 4
112+
```
62113

63114
## Example
64115

65-
- TODO
116+
- <a href="https://www.acmicpc.net/problem/16134" target="_blank">16134번: 조합 (Combination)</a>
117+
118+
```kotlin
119+
import java.io.*
120+
121+
const val p = 1000000007
122+
123+
fun main() {
124+
val br = BufferedReader(InputStreamReader(System.`in`))
125+
val bw = BufferedWriter(OutputStreamWriter(System.out))
126+
127+
// 0 <= r <= n <= 1,000,000
128+
val (n, r) = br.readLine().split(" ").map { it.toInt() }
129+
br.close()
130+
131+
val factorial = LongArray(n + 1) { 0 }
132+
factorial[0] = 1L
133+
factorial[1] = 1L
134+
for (i in 2..n) {
135+
factorial[i] = (i * factorial[i - 1]) % p
136+
}
137+
138+
val result = factorial[n] * expdiv(factorial[r] * factorial[n - r] % p, p - 2) % p
139+
140+
bw.write("$result")
141+
bw.flush()
142+
bw.close()
143+
}
144+
145+
fun expdiv(n: Long, e: Int): Long {
146+
return when (e) {
147+
0 -> 1
148+
1 -> n
149+
else -> {
150+
val temp = expdiv(n, e / 2)
151+
if (e % 2 == 0) (temp * temp) % p else (((n * temp) % p) * temp) % p
152+
}
153+
}
154+
}
155+
```
66156

67157
## 참고 자료
68158

0 commit comments

Comments
 (0)