0. 주어진 문제 |
문제
최근에 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을 출력한다.
1. 풀이 |
1차 시도
for문을 활용하여 만들었지만, 주어지는 값이 커질수록 시간이 오래 걸리는 한계가 있었다. 그 결과 시간 제한을 초과하는 문제가 있었다. O(M*N)이 되어 제한시간을 초과하였다.
2차 시도
시간초과를 막기 위한 방법을 생각해보았다.
O(n)으로 바꾸기 위해 x는 고정하고 y만 변화시키면서 입력과 비교를 하였다.
추가로 찾아보던중 삼항 연산자라는 것을 발견하여 활용하여 보았다.
2. 소스코드 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include <iostream> //아이디어 // 1.최소공약수를 구해내자. int find_year(const int x_max,const int y_max,const int x,const int y) { int compare_x(1), compare_y(1), count(1); for (count = 1;count <= x_max * y_max;count++) { if (compare_x > x_max) compare_x = 1; if (compare_y > y_max) compare_y = 1; if (compare_x == x && compare_y == y) return count; compare_x++; compare_y++; if (compare_x == x_max && compare_y == y_max) return -1; } } int main() { int test,input_m,input_n,input_x,input_y; std::cin >> test; for(int i=0;i<test;i++){ std::cin >> input_m>>input_n>>input_x>>input_y; std::cout << find_year(input_m,input_n,input_x,input_y) << "\n"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include <iostream> // 최대공약수 int gcm(int a, int b) { int c; while (b) { c = a % b; a = b; b = c; } return a; } //최소공배수 int lcm(int a, int b) { return (a*b) / gcm(a, b); } // int find_year(int m,int n,int x,int y) { if (x == y) return x; int count(x), temp_y(x); for (int i = 0; i < n; i++) { //삼항 연산자 int ty = temp_y % n == 0 ? n : temp_y % n; if (ty == y) { break; } temp_y = ty + m; count += m; } return count > lcm(m, n) ? -1 : count; } int main() { int test,m,n,x,y; std::cin >> test; for(int i=0;i<test;i++){ std::cin >> m>>n>>x>>y; std::cout << find_year(m,n,x,y) << "\n"; } } | cs |
3. 문제 출처 |
https://www.acmicpc.net/problem/6064
4. 참고 |
유클리드 호제법
-https://ko.wikipedia.org/wiki/%EC%9C%A0%ED%81%B4%EB%A6%AC%EB%93%9C_%ED%98%B8%EC%A0%9C%EB%B2%95
https://blockdmask.tistory.com/259
삼항 연산자
https://dojang.io/mod/page/view.php?id=145
'<백준> > |C++| hard' 카테고리의 다른 글
[C++] 백준 1874 - 스택 수열 (2) | 2019.03.14 |
---|---|
백준 1181 - 단어 정렬(sort에서 compare함수 만들기, vector에서 erase활용) (0) | 2019.03.05 |
백준 2775 - 부녀회장이 될테야(메모이제이션 활용, 파울하버의 공식, 베르누이 수열) (0) | 2019.02.20 |
백준 1011 - Fly me to the Alpha Centauri(재귀호출, sqrt) (0) | 2019.02.19 |
백준 2448 - 별 찍기11(프렉탈) (0) | 2019.02.09 |