읽기 전
- 불필요한 코드나 잘못 작성된 내용에 대한 지적은 언제나 환영합니다.
- 개인적으로 배운 점을 정리한 글입니다.
문제 링크
문제 풀이 - 1(시간초과)
문제를 보니 주어진 기준값 M, N을 기점으로 초기화된다는 점에서 합동식을 떠올릴 수 있다. 즉 2개의 연립 합동식을 푸는 문제로 해석할 수 있으니 최소공배수를 구해서 계수를 정리한 뒤 카잉 달력 표기법으로 바꿔서 동일한 지 체크하면 된다.
python 코드
import sys def LCD(M, N): i, j = M, N while j != 0: r = i % j i = j j = r L = (M * N) // i return L, L // M, L // N def check(k, M, N, x, y): i, j = k % M, k % N if i == 0: i = M if j == 0: j = N if x != i or y != j: return False return True T = int(input()) for _ in range(T): M, N, x, y = map(int, sys.stdin.readline().split()) p, a, b = LCD(M, N) q = a - b k = x * a - y * b while k % q != 0: k += p k //= q if k < 0: k += p if check(k, M, N, x, y): print(k) else: print(-1)
그러나 이 해결법은 시간초과(TLE)가 발생한다. 아마도 최소공배수를 각각에 대해 구하는 과정에서 TLE가 발생하지 않았나 싶다. 그렇다면 시간 복잡도를 더 줄여야 한다. 검토 가능한 범위의 최대값은 M * N이니 해당 범위에서 어떻게 줄여나갈 지 고민해야 한다.
문제 풀이 - 2
최소공배수를 구하고 또 합동식을 해결하느라 while문 2개가 들어가버리는 바람에 시간초과가 된 듯 싶다. 그렇다면 최대 범위를 상정해 두고 최대한 간격을 띄우면서 탐색을 진행하여 조건에 맞는 값이면 그대로 중지하고 값을 반환하는 1차원적 풀이를 생각해야 한다.
python 코드
import sys T = int(input()) for _ in range(T): M, N, x, y = map(int, sys.stdin.readline().split()) k = x # 기준값 sol = -1 # 값이 없으면 -1 if x == M: # 합동식 0으로 치환 x = 0 if y == N: y = 0 while k <= M * N: # 최대범위까지 if k % N == y: # 만약 k가 N에 대해서도 y를 만족 시 sol = k # 값 발견 break # 탐색 중지 k += M # 아니면 M을 더함 (k mod M 유지) print(sol) # sol 출력
좀 더 M, N 값에 대해 x, y의 조건을 건다던지 제약을 둬서 시간을 절반까지 줄일 수 있어 보인다. (예를 들면 M, N이 모두 짝수일 때, x + y가 홀수라면 무조건 -1) 시간복잡도는 O(n)이다.
'Algorithms > Baekjoon' 카테고리의 다른 글
BOJ #7569 토마토 (0) | 2021.06.03 |
---|---|
BOJ #10799 쇠막대기 (0) | 2021.05.30 |
BOJ #1629 곱셈 (0) | 2021.05.07 |
BOJ #1699 제곱수의 합 (0) | 2021.04.24 |
BOJ #1009 분산처리 (0) | 2021.04.24 |