1. 페르마의 소정리(Fermat's little Theorem)
1-1) p가 소수이고, a가 p의 배수가 아니면( = a와 p가 서로소이면 = gcd(a,p) = 1)이면,
ap−1≡1(modp)이다.
1-2) p가 소수이면, 모든 정수 a에 대하여 ap≡a(modp)
응용하는 방법은 여러가지가 있겠지만, 하나하나 다 나열할 수도 없고, 접한지 얼마 안되었으니 나도 다 모르고
증명도 굳이 할 필요없을 것 같고, 받아들이면서
문제를 풀면서 익혀보기로 하자
2. 응용 - 합성수 판정
페르마의 소정리 역은 성립하지 않는다.
즉, a와 p가 서로소일때, ap−1≡1(modp)가 성립한다면, p는 소수이다는 거짓이다.
즉, a,p가 서로소이면서 p가 합성수인데 ap−1≡1(modp)를 만족하는 수는 무한히 많다는 것이 증명되어 있다.
페르마의 소정리 대우는
어떤 수 n이 적당한 a에 대해 an≢a(modn)이면, n은 합성수이다.
그러므로, n이 합성수라는 것은 확실하게 판정할 수 있다.
3. 응용 - 모듈로 곱셈의 역원
사실 페르마 소정리의 가장 중요한 응용중 하나로 반드시 익혀야 하는 부분인데,
먼저 합동식에서 양변에 같은 수를 곱해도 성립한다
즉, a≡b(modm)이면, 어떤 정수 c에 대하여 ac≡bc(modm)는 항상 성립한다.
여기서 중요한건 c가 정수라는 것임
그러니까 c가 실수면 성립하지 않아
자꾸 실수하는 부분..
합동식하면 기본적으로 정수만 다룬다는 점을 생각해야함
곱했는데 왜 나머지가 달라지지? 실수를 곱한건 아닌지 생각해보자.
------------------------------------------------------------------------------------------------------------------
이거의 연장선상으로 합동식에서 양변을 어떤 수로 나누는 것은 일반적으로 성립하지 않는다.
즉, ac≡bc(modm)이라고 해서, 어떤 정수 c에 대해 a≡b(modm)은 성립하지 않는다.
그러면 합동식에서 어떤 정수 a로 나눌려면 어떤 경우에 가능한가?
a×a−1≡1(modm)
를 만족하는 a−1가 존재해야, mod m에 대한 연산에서 정수 a로 나눌 수 있다.
그것이 가능할려면, a와 m이 서로소인경우에만 가능한 것이 알려져있다.
----------------------------------------------------------------------------------------------------------------------
그러면 a−1를 어떻게 구하는지가 하나의 관심사이다.
가장 기본 형태는 m이 소수일때 페르마의 소정리를 이용하는 것이다.
m이 소수이고 a와 m이 서로소이면 완벽하게 페르마의 소정리에 의해 am−1≡1(modm)이다.
그러므로, a×am−2≡1(modm)
따라서, a−1=am−2
그러므로, m이 소수이고 a,m이 서로소이면 합동식의 양변을 a로 나누는 것은 양변에 am−2를 곱하는 것과 같다.
4. 연습문제
24059번: Function (acmicpc.net)
24059번: Function
As a note, the exact value of 999 has a whopping 369693700 digits.
www.acmicpc.net
f(0)=a0이고, f(i)=af(i−1)i일때, f(n)을 m으로 나눈 나머지를 구하는 문제
5. 풀이
n이 0,1,2 3가지밖에 없다.
n이 0이면 단순히 f(0)=a0이므로, a0modm을 구하면 된다.
n이 1이면 f(1)=aa01이므로, 거듭제곱을 하면서, 나머지를 취하는 방식으로 빠르게 나머지를 구할 수 있다
from sys import stdin
#분할정복을 이용한 거듭제곱
def power(a,f,m):
result = 1
while f >= 1:
if f % 2 == 1:
result *= a
a *= a
a %= m
f = f // 2
return result % m
n = int(stdin.readline())
a_list = list(map(int,stdin.readline().split()))
m = int(stdin.readline())
if n == 0:
print(a_list[0] % m)
elif n == 1:
print(power(a_list[1],a_list[0],m))
근데 문제는 n=2인 경우이다.
n=2인 경우, f(2)=af(1)2이다.
그런데 a,n,m이 너무 커서 f(1)을 구해버리면 시간안에 당연히 못구함
여기서 m이 소수이기 때문에 페르마의 소정리를 생각해보자.
a2,m이 서로소이면, am−12≡1(modm)
그래서 f(1)=aa01을 m-1로 나눈 나머지 f(1) mod (m-1)은 로그 시간에 구할 수 있다는 것은 알고있다.
이것을 이용해보자.
f(1) mod(m-1)은 f(1)을 m-1로 나눈 나머지이다.
그렇다면, f(1)을 어떻게 표현할 수 있을까?
f(1)을 m-1로 나눈 몫을 p라고 하면, f(1)=(m−1)p+f(1)(mod(m−1))
따라서 우리가 구하고자 하는 값은..?
f(2)=a(m−1)p+f(1)(mod(m−1))2을 m으로 나눈 나머지이다.
이제 여기서 여러가지로 나뉜다.
만약에, f(1)이 m-1보다 작다면? 그러면 p=0이므로, f(2)를 m으로 나눈 나머지는..?
f(2)=af(1)(mod(m−1))2을 m으로 나눈 나머지와 같다.
f(1)(mod(m-1))은 로그 시간에 구할 수 있어서, 마찬가지로 f(2)도 로그 시간에 구해진다.
이번엔 f(1)이 m-1보다 크다면? p가 1 이상이므로, f(2)=a(m−1)p+f(1)(mod(m−1))2을 구해야한다.
식을 조금 변형해보면..
f(2)=a(m−1)p2×af(1)(mod(m−1))2
그러면, f(2) mod m은... 합동식의 곱셈 성질로부터
[a(m−1)p2(modm)×af(1)(mod(m−1))2(modm)](modm)
af(1)(mod(m−1))2(modm)은 아주 빠른 시간에 구할 수 있고, 문제는 이제 a(m−1)p2(modm)이다.
이제 여러가지 경우로 나뉜다.
만약에 a2와 m이 서로소라면?
그러면 페르마의 소정리에 의해.. am−12≡1(modm)이므로, 거듭제곱을 해도 변함없으므로,
a(m−1)p2≡1(modm)이다.
서로소인 것을 어떻게 알 수 있을까?
m이 소수이므로, a2가 m보다 큰지, 작은지 판단해야한다.
만약에 a2가 m보다 크다면? a2를 m으로 나눈 나머지가 0이 아니라면... 서로소라는 뜻이다.
하지만 나머지가 0이라면?
그러면 우리는 a2≡0(modm)를 얻는다.
그러므로 당연히, a2를 양변에 계속 곱해서, af(1)2≡0(modm)이다.
그런데, a2가 m보다 작거나 같을 수 있다.
그런 경우에는 m이 소수이므로, a2가 m과 같으면 서로소가 아니고, m과 다르면 서로소가 된다.
이때, a2가 m과 같다면?
그러면 a2≡0(modm)이므로, af(1)2≡0(modm)
따라서... 최종 코드는..
from sys import stdin
def power(a,f,m):
result = 1
while f >= 1:
if f % 2 == 1:
result *= a
a *= a
a %= m
f = f // 2
return result % m
n = int(stdin.readline())
a_list = list(map(int,stdin.readline().split()))
m = int(stdin.readline())
if n == 0:
print(a_list[0] % m)
elif n == 1:
print(power(a_list[1],a_list[0],m))
else:
result = 1
big = False
#f(1)이 m-1보다 큰가 작은가?
for _ in range(1,a_list[0]+1):
result *= a_list[1]
if result > m-1:
big = True
break
f1mod = power(a_list[1],a_list[0],m-1)
#f(1)이 m-1보다 작다.
if big == False:
print(power(a_list[2],f1mod,m))
#f(1)이 m-1보다 크거나 같다
else:
#a2가 m보다 크다면?
if a_list[2] > m:
#a2랑 m이 서로소일려면, 나누어 떨어지지 않는다
if a_list[2] % m != 0:
print(power(a_list[2],f1mod,m))
#a2랑 m이 서로소가 아님
#a2는 m으로 나누어 떨어지므로 나머지가 0
else:
print(0)
#a2가 m보다 작거나 같다면...
else:
#a2와 m이 같다면 당연히 나머지가 0이다
if a_list[2] == m:
print(0)
#m이 소수이므로, a2와 m이 서로소이다.
else:
print(power(a_list[2],f1mod,m))
참조
페르마의 소정리 - 나무위키
페르마의 소정리(Fermat's little Theorem)ppp가 소수이면, 모든 정수 aaa에 대해 ap≡a(mod p)a^p\equiv a\left({\rm mod}\ p\right)ap≡a(mod p) 이다.혹은ppp가 소수이고 aaa가 ppp의 배수가 아니면, ap−1≡1(mod p)a^{p-1}\e
namu.wiki
정수론 (4) - 합동식에서의 나눗셈 (tistory.com)
정수론 (4) - 합동식에서의 나눗셈
저번에 우리는 합동식의 나눗셈에 대해 살펴보던 중 어떨 때는 합동식의 양변을 나누는 것이 안되고 어떨 때는 된다는 것을 관찰했습니다. 아래의 합동식은 안되는 예시이며, $$ \begin{align} 15 \equ
dimenchoi.tistory.com
나머지 연산의 곱셈 역원
정수 a를 m으로 나눈 나머지 연산의 곱셈 역원은 a×a−1≡1(modm)을 만족하는 a−1을 말합니다. 즉, a−1≡x(modm)을 만족하는 x를 말합니다. 역원은 a와 m이 서로소인 경우
www.acmicpc.net
합동식 - 나무위키
1. d∤bd\nmid bd∤b인데 해가 존재한다고 가정하자. 그럼 적당한 정수 yyy에 대하여 ax+my=bax+my=bax+my=b가 성립한다. 그런데 d∣ax+my=bd\mid ax+my=bd∣ax+my=b이므로 d∣bd\mid bd∣b이다. 이는 가정에 모순되므
namu.wiki
'정수론' 카테고리의 다른 글
모듈로 연산에서 나눗셈을 하는 방법(모듈로 곱셈의 역원 구하기) (0) | 2022.12.16 |
---|---|
확장된 유클리드 알고리즘(extended euclidean algorithm) 구현해보면서 익히기 (0) | 2022.12.16 |
오일러의 phi 함수 직접 구현해보면서 개념 익히기 (0) | 2022.12.13 |
소인수분해 기본 알고리즘 배우기 (0) | 2022.12.13 |
정수론 - 합과 곱은 왜 계속 나눠도 문제가 없는가? - (0) | 2022.09.09 |