본문 바로가기
Algorithm/BOJ

[BOJ]1476번: 날짜 계산(java, c++)

by HBGB 2020. 1. 6.

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

 

1476번: 날짜 계산

준규가 사는 나라는 우리가 사용하는 연도와 다른 방식을 이용한다. 준규가 사는 나라에서는 수 3개를 이용해서 연도를 나타낸다. 각각의 수는 지구, 태양, 그리고 달을 나타낸다. 지구를 나타내는 수를 E, 태양을 나타내는 수를 S, 달을 나타내는 수를 M이라고 했을 때, 이 세 수는 서로 다른 범위를 가진다. (1 ≤ E ≤ 15, 1 ≤ S ≤ 28, 1 ≤ M ≤ 19) 우리가 알고있는 1년은 준규가 살고있는 나라에서는 1 1 1로 나타낼 수 있다. 1

www.acmicpc.net

 

방법 1 : 나머지 정리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) throws Exception {
 
        // 입력
        Scanner sc = new Scanner(System.in);
        int E = sc.nextInt();
        int S = sc.nextInt();
        int M = sc.nextInt();
 
        // 최소공배수 조건을 충족하는 i 출력
        // 15*a + E = 28*b + S = 19*c + M = X
        for (int i = 1;; i++) {
            if (((i - E) % 15 == 0&& ((i - S) % 28 == 0&& ((i - M) % 19 == 0)) {
                System.out.println(i);
                break;
            }
        }
    }
}
Colored by Color Scripter

 

방법 2 : 최대 범위를 설정하고 거기까지만 계산

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) throws Exception {
 
        // 입력
        Scanner sc = new Scanner(System.in);
        int E = sc.nextInt() - 1;
        int S = sc.nextInt() - 1;
        int M = sc.nextInt() - 1;
 
        // 문제 조건 만족하는 i + 1 출력
        // 15*a + E = 28*b + S = 19*c + M = X
        for (int i = 0;; i++) {
            if ((i % 15 == E) && (i % 28 == S) && (i % 19 == M)) {
                System.out.println(i + 1);
                break;
            }
        }
    }
}
Colored by Color Scripter

 

c++소스

더보기
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
#include <iostream>
 
using namespace std;
 
// 최대범위까지 주어진 조건을 지키는 수 검사
int ESM(int e, int s, int m)
{
    int MAX = 15 * 28 * 19;
    for (int i = 0; i < MAX; i++)
    {
        if (i % 15 == e && i % 28 == s && i % 19 == m)
        {
            return i;
        }
    }
    return 0;
}
 
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
 
    int E, S, M;
    cin >> E >> S >> M;
    
    // 수의 범위가 1 <= x <= N 이므로, 
    // 1씩 빼서 0 <= x - 1 <= N - 1 로 계산
    cout << ESM(E - 1, S - 1, M - 1+ 1;
 
    return 0;
}
Colored by Color Scripter

 

방법 3 : 문제 그대로 구현(c++)

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
#include <iostream>
 
using namespace std;
 
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
 
    int E, S, M;
    cin >> E >> S >> M;
 
    int i = 1, e = 1, s = 1, m = 1;
    while (!(e == E && s == S && m == M))
    {
        i++;
        e++;
        s++;
        m++;
 
        if (e > 15)
        {
            e = 1;
        }
        if (s > 28)
        {
            s = 1;
        }
        if (m > 19)
        {
            m = 1;
        }
    }
 
    cout << i;
 
    return 0;
}
Colored by Color Scripter

 

 

방법 1, 2, 3모두 속도는 같다.

 

 

TIP1

for문에 종료조건을 주지 않아도 된다.

 

 

TIP2

방법 2에서는 입력값에서 -1 씩 해주어야 한다.

이유는 E, S, M의 값이 0을 제외하기 때문에 그렇다. 

 

예를 들면, E는 1 ≤ E ≤ 15 이므로 1, 2, 3 ... 15, 1, 2, 3 ... 15 를 반복한다. 

15를 주기로 반복하게 되므로 i % 15 == E 의 식을 써주면 좋을 것 같은데

i가 30이고 E가 15일 때는 위 식을 만족하지 않는다. 

30 % 15 == 15 (X)

 

따라서 E, S, M의 범위를 1씩 줄여준다.

--> 0≤ (E - 1) ≤ 14, 0 ≤ (S - 1) ≤ 27, 0 ≤ (M - 1) ≤ 18

조건식의 숫자도 1씩 줄여준다. 

--> (i - 1) % 15 == (E - 1)

 

그러면 이제 i가 30, E가 15일 때에도 위 식을 만족할 수 있다.

29 % 15 == 14 (O)

 

마지막으로 출력값에 다시 +1을 해주면 된다.

 

 

길게 썼는데,

결국 2진법은 1, 2가 아니라 0, 1만이 반복된다는 이야기와 동일하다.

간-단!

 

'Algorithm > BOJ' 카테고리의 다른 글

[BOJ]6603번: 로또(java, c++)  (0) 2020.01.18
[BOJ]7568번: 덩치  (0) 2020.01.11
[BOJ]3085번: 사탕 게임(java)  (0) 2020.01.05
[BOJ]2309번: 일곱 난쟁이(java, c++)  (0) 2020.01.04
[BOJ]2225번: 합분해(java)  (0) 2019.10.19

댓글