https://www.acmicpc.net/problem/31478
31478번: 포니 양은 놀고 싶어!
첫 번째 줄에 정수 A, B, C가 주어진다. (1≤A<7, 1≤B,C≤109, BC는 A의 배수) 두 번째 줄에 정수 K와 L이 주어진다. (0≤K,L<7)
www.acmicpc.net
24/04/15
간단한 정수론 문제입니다. 분할 정복을 이용한 거듭제곱에 관한 지식과, 페르마의 소정리에 관한 지식이 있어야 해결할 수 있습니다.
문제 접근 방식:
결국 ABC와 BC/A를 빨리 구하는 문제로 귀결됩니다.
후자는 빠르게 구할 수 있습니다. 결국 7일이라는 범위 안에서만 따지는 것이기 때문에 7에 대한 모듈로 연산을 취해주는 것이고, 7은 소수이기 때문에 A가 어떤 값이든 간에 모듈로 역원을 구할 수 있습니다.
파이썬에서는 모듈로 역원을 pow함수를 통해 간단하게 구할 수 있습니다.
pow(value, power, mod)에서, power인자를 −1로 넘겨주기만 하면 됩니다.
ABC의 mod 7값은 ABC mod 7 mod 7이 아님을 주의합시다.
페르마의 소정리에 의하면, n과 A가 서로소일때, Aϕ(n)≡1(mod n)가 성립함을 알고 있습니다.
이를 이용해봅시다. 우리는 n=7일때의 경우를 따지고 있습니다. n이 소수이고, A는 7보다 작으므로, A의 값과 관계 없이 서로소입니다.
BC의 값이 어느 정도로 큰 지는 잘 모르지만, 이 값을 k라고 한다면, 우리는 Ak mod 7의 값을 구하는 것과 같습니다.
우리는 ϕ(7)=6임을 알고 있으므로, A6≡1 mod 7임을 알고 있습니다.
이를 이용하면, Ak를 A6들의 곱으로 분해할 수 있습니다. 즉, 다음과 같습니다.
Ak≡A6⋅A6⋅⋯⋅Ak mod 6≡1⋅1⋅⋯⋅Ak mod 6≡Ak mod 6 mod 7
따라서, BC를 6으로 나눈 나머지를 구하고 이를 p라고 하면, Ap를 7로 나눈 나머지가 답이 됩니다.
이는 파이썬의 pow함수로 쉽게 구현할 수 있습니다.
아래는 내가 위의 접근 방식과 같이 작성한 파이썬 코드이다. 더보기를 누르면 확인할 수 있다.
# 31478번 포니 양은 놀고 싶어!
# 분할 정복을 이용한 거듭 제곱, 모듈로 역원, 정수론, 오일러파이함수
A, B, C = map(int, input().split())
K, L = map(int, input().split())
p, q = pow(A, pow(B, C, 6), 7), (pow(B, C, 7)*pow(A, -1, 7))%7
if (K+p)%7 == (K+q)%7 == L:
print(3)
elif (K+p)%7 == L:
print(1)
elif (K+q)%7 == L:
print(2)
else:
print(0)
'알고리즘 > 백준 문제 풀이' 카테고리의 다른 글
[Python] 5069번 미로에 갇힌 상근 (0) | 2024.04.19 |
---|---|
[Python] 31532번 선형 회귀는 너무 쉬워 3 (0) | 2024.04.18 |
[Python] 13987번 Six Sides (0) | 2024.04.06 |
[Python] 2357번 최솟값과 최댓값 (추후 보강 예정) (0) | 2024.03.28 |
[Python] 19240번 장난감 동맹군 (0) | 2024.03.27 |