@@ -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 />
5959b의 곱셈 역원은 항상 존재하는 것이 아니라, <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