3955 - 캔디 분배
본문
창영이는 선영이가 사탕을 공평하게 나누어주지 않으면 친구들을 때릴정도로 사탕을 좋아한다.
따라서, 선영이는 다음 파티에 사용할 사탕을 구매하기 전에 고민을 하기 시작했다.
만약 파티에
선영이는 항상 적어도 한 아이는 사탕을 잃어버린다는 사실을 알고 있다. 그래서 캔디를 하나 더 구매해 총 (
사탕은 봉지 단위로 판매한다. 한 봉지에는 사탕이 총
입력
첫째 줄에 테스트 케이스의 개수
출력
각 테스트 케이스에 대해서 문제의 조건을 만족시키면서 구매할 수 있는 사탕 봉지가 없다면, “IMPOSSIBLE”을 출력한다. 이 경우가 아닌 경우에는 선영이가 구매해야 하는 사탕 봉지의 수를 출력한다. 만약, 가능한 봉지의 수가 여러개라면 아무거나 출력한다.
제한
시간 제한 | 메모리 제한 |
---|---|
1sec | 128MB |
풀이
문제를 수식으로 생각해보자. 사람 수를
우리는 위 조건에서
양동이 퍼즐은 그냥 무작정 옮겨보다보면 풀리던 문제였다.
- 양동이를 이용해 물을 더하고 뺄 수 있다
- 다만 이 문제에서는 양동이를 꽉 채운다는 선택지밖에 존재하지 않는다
- 두 양동이로 만들 수 없는 용량도 있다
- 예를 들어, 10L와 2L짜리 양동이로는 홀수의 용량을 만들 수 없다
- 5L와 3L짜리 양동이로는 모든 용량을 만들 수 있었다
위 정보를 이용하여, 결국은 두 양동이를 이용하여 1L을 만들 수 있는가를 판단해야할 필요성이 있다는 것을 알아냈다. 그런데 하나하나 다 시도해볼 수 없으므로 특정 조건을 만들어서 바로 판단할 수 있도록 해야한다. 안되는 경우를 생각해보자. 왜 10L와 2L로는 홀수 용량을 만들 수 없었을까? 반대로 왜 5L와 3L로는 모든 용량을 만들 수 있었을까?
두 수의 최대공약수를 구하려면 사용하는 알고리즘들이 몇개 있을텐데, 그중에서 유명하게 쓰이는게 유클리드 알고리즘 일 것이다. 그런데 유클리드 알고리즘이 문제를 해결할 정보를 전부 주지는 못한다. 그런데 유클리드 알고리즘의 확장판이 있었다. 그리고 그 확장판이, 이 문제를 해결할 수 있는 실마리를 제공하고 있었다.
위에서 찾았던 조건이 ‘베주 항등식’ 이라는 명칭으로 증명이 되어있었다. 그래서,
알고리즘 자체에 대한 설명은 따로 적지는 않겠다. 알고리즘의 단계를 따라가며 최대공약수를 구해보고, 최대공약수가 1이라면
- 참고 알고리즘 : 확장 유클리드 알고리즘
코드
사용 언어 : C
최종 수정일 : 2023 / 3 / 12
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
53
#include <stdio.h>
typedef long long ll;
#define MAX_CNT (ll)(1e9)
void EEA(ll a, ll b) {
ll r1 = a, r2 = b, s1 = 1, s2 = 0, t1 = 0, t2 = 1;
ll r, s, t, q;
while (r2 != 0) {
q = r1 / r2;
r = r1 % r2;
r1 = r2, r2 = r;
s = s1 - q * s2;
s1 = s2, s2 = s;
t = t1 - q * t2;
t1 = t2, t2 = t;
}
s = s1, t = t1;
if (r1 != 1) {
printf("IMPOSSIBLE\n");
} else {
if (s >= 0) {
t += a;
}
#define STD (ll)(1e9)
if (t > STD) {
printf("IMPOSSIBLE\n");
} else {
printf("%lld\n", t);
}
}
return;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
ll a, b;
scanf("%lld %lld", &a, &b);
EEA(a, b);
}
return 0;
}