문제
최근에 ICPC 탐사대는 남아메리카의 잉카 제국이 놀라운 문명을 지닌 카잉 제국을 토대로 하여 세워졌다는 사실을 발견했다. 카잉 제국의 백성들은 특이한 달력을 사용한 것으로 알려져 있다. 그들은 M과 N보다 작거나 같은 두 개의 자연수 x, y를 가지고 각 년도를 <x:y>와 같은 형식으로 표현하였다. 그들은 이 세상의 시초에 해당하는 첫 번째 해를 <1:1>로 표현하고, 두 번째 해를 <2:2>로 표현하였다. <x:y>의 다음 해를 표현한 것을 <x':y'>이라고 하자. 만일 x < M 이면 x' = x + 1이고, 그렇지 않으면 x' = 1이다. 같은 방식으로 만일 y < N이면 y' = y + 1이고, 그렇지 않으면 y' = 1이다. <M:N>은 그들 달력의 마지막 해로서, 이 해에 세상의 종말이 도래한다는 예언이 전해 온다.
예를 들어, M = 10 이고 N = 12라고 하자. 첫 번째 해는 <1:1>로 표현되고, 11번째 해는 <1:11>로 표현된다. <3:1>은 13번째 해를 나타내고, <10:12>는 마지막인 60번째 해를 나타낸다.
네 개의 정수 M, N, x와 y가 주어질 때, <M:N>이 카잉 달력의 마지막 해라고 하면 <x:y>는 몇 번째 해를 나타내는지 구하는 프로그램을 작성하라.
입력
입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터는 한 줄로 구성된다. 각 줄에는 네 개의 정수 M, N, x와 y가 주어진다. (1 ≤ M, N ≤ 40,000, 1 ≤ x ≤ M, 1 ≤ y ≤ N) 여기서 <M:N>은 카잉 달력의 마지막 해를 나타낸다.
출력
출력은 표준 출력을 사용한다. 각 테스트 데이터에 대해, 정수 k를 한 줄에 출력한다. 여기서 k는 <x:y>가 k번째 해를 나타내는 것을 의미한다. 만일 <x:y>에 의해 표현되는 해가 없다면, 즉, <x:y>가 유효하지 않은 표현이면, -1을 출력한다.
문제 풀이
구하고자 하는 해가 k라고 할 때,
k = x + M*p = y + N*q (k <= M*N)
이라는 식을 얻을 수 있다.
x에 M을 더해도 결과는 x이고, 2M을 더해도, 3M을 더해도,... 몇번을 더하더라도 x에 M의 배수를 더한 결과는 x이기 때문이다. (y도 마찬가지)
즉, 위의 식을 통해
(k-x)%M = 0
(k-y)%N =0
이라는 식또한 도출해낼 수 있다.
x, y 둘 중 하나의 값만을 이용해서 k를 구할 수 있는데,
여기서 주의할 점은 해당 식을 이용해서 k값을 구할 때 +1 씩 증가시키면서 확인하면 시간초과가 발생한다는 것이다.
x를 고정시켜서 k값을 확인하고자할 때, 두 가지 방법의 조건식으로 구할 수 있다.
# 방법 1.
(k-x)%M = 0 을 이용하면, (k-x)는 M의 배수임을 알 수 있다.
즉, k를 x로 초기화한 후, 추가적으로 M만 더해주면서 (k-x)%M = 0 && (k-y)%N =0 조건식을 검사하는 것이다.
# 방법 2.
k는 x에 M을 계속 더한 값이거나 y에 N을 계속 더한 값 중 하나이다.
k = x + M*p = y + N*q
이를 x를 기준으로 정리하면
x + M*p - y = N*q
이므로, x에 M을 계속 더해주면서 (x-y)%N 조건식을 검사하면 된다.
작성 코드
# 방법1 (2548ms)
def cain(M, N, x, y):
k = x
# k의 범위는 M*N을 넘을 수 없음
while k <= M * N:
if (k - x) % M == 0 and (k - y) % N == 0:
return k
# (k-x)가 M의 배수이고, k는 x로 초기화해주었기 때문에 m만 더해준다
k += M
return -1
# 방법2 (1868ms)
def cain(M, N, x, y):
# k의 범위는 M*N을 넘을 수 없음
while x <= M * N:
if (x - y) % N == 0:
return x
x += M
return -1
T = int(input())
for _ in range(T):
M, N, x, y = map(int, input().split())
print(cain(M, N, x, y))
'Problem Solving' 카테고리의 다른 글
[백준] 13023 - ABCDE in 파이썬 (1) | 2022.09.30 |
---|---|
[백준] 1748 - 수 이어쓰기1 in 파이썬 (0) | 2022.09.19 |
[백준] 2193 - 이친수 in 파이썬 (0) | 2022.09.05 |
[백준] 10844 - 쉬운 계단 수 in 파이썬 (0) | 2022.09.05 |
[백준] 15990 - 1, 2, 3 더하기2 in 파이썬 (0) | 2022.09.04 |