백준 문제

백준 6064 (카잉 달력) c++

kangyuseok 2022. 8. 7. 14:25
728x90

문제

 

6064번: 카잉 달력

입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터는 한 줄로 구성된다.

www.acmicpc.net

m과 n이 주어지고 x와 y가 주어지면 <x, y>가 몇번째로 이루어지는지 구하는 문제입니다.

만약 <x, y>가 안되면 -1을 출력하면 됩니다.

<1, 1> 부터 시작하며 x' n을 넘어가면 다시 x'가 1로 되고 y도 마찬가지 입니다.

예를 들어 m과 n이 10, 12 라면

<1, 1> 부터 시작해 <10, 10> 까지 가고 <11, 11>은 x'가 m을 넘어가 되므로 <10, 10> 다음에는 <1, 11> 이 됩니다.

마찬가지로 <2, 12>가 되고 다음 순서는 <3, 13> 이 되어야 하지만 y'가 n을 넘어가게 되므로 <3, 12>가 됩니다.

 

<10, 12> 는 60번째 에서 마지막이 되고 끝이 납니다.

 

단순히 <x, y>가 될 때 까지 반복문을 돌리게 되면 시간초과가 나게 됩니다.

 

따라서 새로운 방법을 구해야 합니다.

요점은 바로 x를 기준으로 맞춘다는 것입니다. 즉, x를 기준으로 하면 y만 신경 써주면 됩니다.

예를 들어 m과 n이 <10 ,12> 이고 x와 y가 <3, 9> 라면

x가 3이므로 3일 경우에만 y를 판별해 주면 됩니다.

y는 n까지 증가하므로 나머지 연산을 통해 판별해주면 됩니다. 

먼저 처음에 x = 3일 경우

x = 3

y = 3 % 12 = 3

 

다음에 x가 3일 경우에는 x는 m만큼 증가 하므로 m을 더해주면 됩니다.

x = (3 + 10) = 3

y = (3 + 10) % 12 = 1

 

x = ( 3 + 10 + 10) = 3

y = (3 + 10 + 10) % 12 = 11

 

x = (3 + 10 + 10 + 10) = 3

y = (3 + 10 + 10 + 10) % 12 = 9

따라서 (3 +10 +10 +10)번의 연산을 했을 때 <3, ,9> 가 나오므로 정답은 (3 + 10 + 10 +10) = 33이 됩니다.

 

하지만 만약 답이 될 수 없는 경우도 있습니다. 그렇게 되면 계속 해서 반복문이 실행이 되고 결국 시간초과가

나오게 됩니다.

문제에서의 힌트는 m과 n이 <10, 12>의 경우에는 최종 해가 <10, 12> 가 되어 60번째에서 끝이 나게 됩니다.

즉, m과 n의 최소공배수에서 끝이 납니다. 

만약 최소공배수를 넘어가게 되면 해당 x와 y는 답이 될 수 없습니다.

다음과 같이 gcd를 먼저 구해주면 lcm(최소공배수)를 구할 수 있습니다.

lcm으로 나온 수를 lim에 넣어주고 lim까지 반복문을 돌려 줍니다.

i가 lim을 넘어가게 되면 정답이 없는 것이므로 -1을 출력해줍니다.


전체 코드 입니다.

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
48
49
50
51
52
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <map>
#include <set>
#include <tuple>
#define MAX 2100000000
#define inf LONG_MAX
#define big(a, b) a > b ? a : b
using namespace std;
using ll = long long;
using ull = unsigned long long;
int gcd(int a, int b);
int lcm(int a, int b);
int main() {
    ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
    int t;
    cin >> t;
    while (t--) {
        int m, n, x, y, i;
        cin >> m >> n >> x >> y;
        int lim = lcm(m, n);
        for (i = x; i <= lim; i += m) {
            int temp = (i % n == 0) ? n : i % n;
 
            if (temp == y) {
                cout << i << '\n';
                break;
            }
        }
        if (i > lim)
            cout << -1 << '\n';
    }
 
 
 
    return 0;
}
int gcd(int a, int b) {
    if (!b)
        return a;
    return gcd(b, a % b);
}
int lcm(int a, int b) {
    return a * b / gcd(a, b);
}
cs