[백준 C++] 28706번 럭키 세븐
백준 28706번 럭키 세븐 c++로 풀이
[백준 C++] 28706번 럭키 세븐
28706번: 럭키 세븐
문제 요약
문제
당신은 양의 정수 $K$를 하나 가지고 있습니다. 처음에 $K=1$입니다. 당신에게는 $N$개의 턴이 주어지고, 각 턴에는 $2$개의 선택지 중 하나를 골라야합니다. 각각의 선택지는 “+ $v$ ” 혹은 “* $v$ ”와 같은 방식으로 주어집니다. $(1 \le v \le 9)$
- “+ $v$ ”: $K$를 $K + v$로 바꿉니다.
- “* $v$ ”: $K$를 $K \times v$로 바꿉니다.
선택지를 모두 고른 이후 결과로 나온 $K$가 $7$의 배수가 되도록 할 수 있나요?
사용 알고리즘
다이나믹 프로그래밍
입출력
- 입력: 첫 줄에 테스트케이스의 수 $T$가 주어집니다. $(1 \le T \le 10\,000)$ 각 테스트케이스의 첫 줄에 턴의 수 $N$이 주어집니다. $(1 \le N \le 200\,000)$ 다음 $N$개의 줄의 $i$번째 줄은 “ $op_1$ $v_1$ $op_2$ $v_2$ ”와 같은 방식으로 모든 문자를 공백으로 구분하여 주어집니다. $op_1$과 $op_2$는 ‘+’ 혹은 ‘*’이며, $v_1$과 $v_2$는 $1$ 이상 $9$ 이하의 정수입니다. 이는 $i$번째 턴의 선택지가 “ $op_1$ $v_1$ ”과 “ $op_2$ $v_2$ ”라는 것을 의미합니다. 모든 테스트케이스에서 $N$의 합이 $200\,000$을 넘지 않습니다.
- 출력: 각 테스트케이스마다 한 줄에 하나씩, $K$를 $7$의 배수로 만들 수 있다면 “LUCKY”, 불가능하다면 “UNLUCKY”를 출력하세요. ``` 예제1
입력 3 1
- 3 + 6 2
- 3 + 6
- 1 + 2 5
- 3 * 1
- 4 + 5
- 9 * 2
- 6 + 3
- 5 + 5 출력 LUCKY UNLUCKY LUCKY ```
풀이
이 문제는 7로 나눈 나머지가 0~6까지 총 7가지뿐이라는 점을 활용하는 DP 문제다. 모든 수식을 직접 계산해 나가는 게 아니라, 나머지가 같은 경우만 추적하면 되기 때문에 상태 수를 줄일 수 있다. 즉, 특정 시점에서 나머지가 동일하다면, 그 이후의 선택은 중복되므로 같은 상태로 처리할 수 있다. DP 배열은
dp[i][r] = true/false
형식으로 구성해서, - i번째 줄까지 처리했을 때,
- 나머지가 r인 경우가 가능한지 여부를 저장한다. 각 줄마다 연산이 두 가지(
+
,*
)가 주어지고, 현재 가능한 나머지 상태들로부터 두 연산 결과에 해당하는 새로운 나머지를 갱신해 나간다. 모든 줄을 처리한 후dp[n][0]
이true
라면, 7로 나누어 떨어지는 경우가 존재한다는 뜻이다. 이처럼 모든 수식을 실제로 계산하는 대신 나머지 상태만 관리하면 효율적으로 풀 수 있는 문제다.
어려웠던 점
나머지를 확인한다는 아이디어가 살짝 힘들었다.
배운 점 / 느낀 점
없다.
전체 코드
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
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int T, n;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> T;
for(int _ = 0; _ < T; _++){
cin >> n;
int v1, v2;
char op1, op2;
vector<vector<bool>> a(n+1, vector<bool>(7, false));
a[0][1] = true;
for(int i = 1; i <= n; i++){
cin >> op1 >> v1 >> op2 >> v2;
for(int j = 0; j < 7; j++){
if(!a[i-1][j]){
continue;
}
if(op1 == '+'){
a[i][(j+v1)%7] = true;
}
else{
a[i][(j*v1)%7] = true;
}
if(op2 == '+'){
a[i][(j+v2)%7] = true;
}
else{
a[i][(j*v2)%7] = true;
}
}
}
if(a[n][0]){
cout << "LUCKY\n";
}
else{
cout << "UNLUCKY\n";
}
}
return 0;
}
This post is licensed under CC BY 4.0 by the author.