[백준(baekjoon) 6064] (최대공약수/규칙 찾기) 카잉 달력
2017. 12. 1. 17:58ㆍAlgorithm
반응형
문제 백준 6064
M, N, X, Y가 주어질 때 가 몇 번째 해인지 구하여라.
단, 답이 존재 하지 않는 다면 -1
1 <= M,N <= 40,000
이고 첫번째 해가 <1:1>이고 마지막 해가 인 달력이 있다.1 <= x <= M, 1 <= y <= N
인 수로 년도를 로 표현함.- <x, y>의 다음 해를 <x':y'>라고 할 때
x' = x + 1
이지만,x' > m
이면x' = 1
(y 역시 n에 대하여 동일)
해결
1. 정답이 존재할 경우, 정답은 다음과 같이 나타낼 수 있다.
자연수 a, b가 있을 때
answer = Ma + x = Nb + y
즉, x와 y는 정답에서 M, N을 나눈 나머지 가 됨을 알 수 있다.
(단 M = x, N = y일 경우 0이 되므로 이 경우를 고려한다.)
x = 정답 % a
y = 정답 % b
2. answer = Ma + x = Nb + y
을 활용해 정답을 구할 수 있을 것 같다.
M
,x
를 알고있으므로a
를 1부터 1씩 증가시켜서num = Ma + x
를 구한다.num
이 정답이라면num % N == y
일 것이다.
3. 그리고 여기서 시간을 더 줄여보자.
(이 과정을 거치지 않아도 통과 가능하긴 합니다.)
2번 과정에서 num
을 구하기 위해 증가하는 a
의 횟수가 실행시간에 중요한 역할을 한다.
그리고 당연히 이 a
대신 b
를 증가시켜도 된다.
그렇다면 M
, N
중 큰 수를 기준으로 삼아 num
을 구하면 당연히 실행횟수가 줄어들 것.
1.ex) answer = 39999, M = 39999, N = 1일때 a = 1, b = 39999가 된다.
answer = Ma + x = Nb + y
여기서 M <= N이라면, a >= b 이다.
즉 2번에서 num
을 구하는 M
역할을 M, N 중 큰 수로 대체한다.
4. 그렇다면 -1이 되는 경우는 언제인가?
마지막 해는 M, N의 [최대공약수]번째에 나타난다.
마지막 해는 x = M
, y = N
을 만족한다. 1번에 대입하면 x = 0
, y = 0
이다.
즉, 정답을 M
, N
으로 나눈 나머지가 0을 만족한다는 것을 뜻한다.
M
, N
을 나눈 나머지가 0이라는 말은 즉 M
, N
의 최대공약수를 뜻한다.
즉, 정답은 최대공약수 보다 작다.
이를 활용해 최대공약수를 벗어날 경우 -1이 답 임을 알 수 있다.
구현
언어 : swift
1.import Foundation
2.
3.// 최대공약수 구하는 함수
4.func getLcm(l: Int, s: Int) -> Int {
5. var large = l; var small = s
6. var rest = large % small
7. while rest > 0 {
8. large = small
9. small = rest
10. rest = large % small
11. }
12. return l * s / small
13.}
14.
15.let count = Int(readLine()!)!
16.// 정답을 우선 -1로 모두 초기화 한다.
17.var answer = Array(repeatElement(-1, count: count))
18.for i in 0..<count {
19. var input = readLine()!.split(separator: " ").map{ Int($0)! }
20.
21. // 쉬운 구현을 위해
22. // m = x, n = y인 경우 0으로 변경해준다.
23. input[2] = input[2] == input[0] ? 0 : input[2]
24. input[3] = input[3] == input[1] ? 0 : input[3]
25.
26. // m, n 중 큰 수와 작은 수의 인덱스를 각각 l, s에 저장한다.
27. // x, y의 위치는 l, s에 2를 더한 곳이다.
28. let l = input[0] > input[1] ? 0 : 1; let s = abs(l - 1)
29. let lcm = getLcm(l: input[l], s: input[s])
30. // num의 큰 수의 나머지 부터 시작하지만
31. // 나머지가 0인 경우 num은 자연수 이므로 큰 수부터 시작한다.
32. var num = input[l + 2] > 0 ? input[l + 2] : input[l]
33.
34. // num이 최대공약수보다 클 수 없다.
35. while num <= lcm {
36. if num % input[s] == input[s + 2] {
37. answer[i] = num
38. break
39. }
40. num += input[l]
41. }
42.}
43.
44.for a in answer {
45. print(a)
46.}
반응형