Loading [MathJax]/jax/output/CommonHTML/jax.js
본문 바로가기

알고리즘/백준 문제 풀이

[Python] 31478번 포니 양은 놀고 싶어!

728x90

https://www.acmicpc.net/problem/31478

 

31478번: 포니 양은 놀고 싶어!

첫 번째 줄에 정수 A, B, C가 주어진다. (1A<7, 1B,C109, BCA의 배수) 두 번째 줄에 정수 KL이 주어진다. (0K,L<7)

www.acmicpc.net


 

24/04/15

 

 

간단한 정수론 문제입니다. 분할 정복을 이용한 거듭제곱에 관한 지식과, 페르마의 소정리에 관한 지식이 있어야 해결할 수 있습니다.


 

문제 접근 방식:

 

 

결국 ABCBC/A를 빨리 구하는 문제로 귀결됩니다.

 

후자는 빠르게 구할 수 있습니다. 결국 7일이라는 범위 안에서만 따지는 것이기 때문에 7에 대한 모듈로 연산을 취해주는 것이고, 7은 소수이기 때문에 A가 어떤 값이든 간에 모듈로 역원을 구할 수 있습니다.

 

파이썬에서는 모듈로 역원을 pow함수를 통해 간단하게 구할 수 있습니다.

 

pow(value, power, mod)에서, power인자를 1로 넘겨주기만 하면 됩니다.

 

ABC의 mod 7값은 ABC mod 7 mod 7이 아님을 주의합시다.

 

페르마의 소정리에 의하면, nA가 서로소일때, Aϕ(n)1(mod n)가 성립함을 알고 있습니다.

 

이를 이용해봅시다. 우리는 n=7일때의 경우를 따지고 있습니다. n이 소수이고, A7보다 작으므로, A의 값과 관계 없이 서로소입니다.

 

BC의 값이 어느 정도로 큰 지는 잘 모르지만, 이 값을 k라고 한다면, 우리는 Ak mod 7의 값을 구하는 것과 같습니다.

 

우리는 ϕ(7)=6임을 알고 있으므로, A61 mod 7임을 알고 있습니다.

 

이를 이용하면, AkA6들의 곱으로 분해할 수 있습니다. 즉, 다음과 같습니다.

 

AkA6A6Ak mod 611Ak mod 6Ak mod 6 mod 7

 

따라서, BC6으로 나눈 나머지를 구하고 이를 p라고 하면, Ap7로 나눈 나머지가 답이 됩니다.

 

이는 파이썬의 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)