문제
https://www.acmicpc.net/problem/20500
풀이(10분)
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*
private const val MOD = 1_000_000_007
fun main() {
val br = BufferedReader(InputStreamReader(System.`in`))
var st: StringTokenizer
st = StringTokenizer(br.readLine())
val N = st.nextToken().toInt()
val arr = Array(N + 1) { Array(3) { 0 } } // 3으로 나누었을 때 나머지가 0 1 2
arr[1][1] = 1 // 1일 때는 3으로 나눈 경우 나머지가 1
arr[1][2] = 1 // 5일 때는 3으로 나눈 경우 나머지가 1
for (i in 2..N) {
arr[i][0] = (arr[i - 1][2] + arr[i - 1][1]) % MOD// 이전에 나머지가 2인 경우 1과 합치면 0, 1인 경우 5와 합치면 0
arr[i][1] = (arr[i - 1][0] + arr[i - 1][2]) % MOD // 이전에 나머지가 0인 경우 1과 합치면 1, 2인 경우 5와 합치면 1
arr[i][2] = (arr[i - 1][0] + arr[i - 1][1]) % MOD // 이전에 나머지가 0인 경우 5와 합치면 2, 1인 경우 1과 합치면 2
}
println(arr[N - 1][1])
}
문제 풀이 전략
💡 문제 접근
이 문제는 1과 5로만 이루어진 수 중 15의 배수가 되는 경우의 수를 구하는 문제다.
먼저, 15의 배수 판별법부터 생각해볼 필요가 있다.
🔹15의 배수 판별법
15를 소인수분해하면
15=3×515 = 3 \times 5
따라서 15의 배수는 3의 배수이면서 동시에 5의 배수여야 한다.
🔹 5의 배수 판별
5의 배수는 끝자리가 0 또는 5인 수다.
하지만 이 문제에서는 사용할 수 있는 숫자가 1과 5뿐이다.
따라서 끝자리가 0인 경우는 존재하지 않으며,
15의 배수가 되기 위해서는 반드시 끝자리가 5여야 한다.
🔹 3의 배수 판별
3의 배수는 각 자리 숫자의 합이 3의 배수인 수다.
즉, 1과 5로 이루어진 수라면 각 자리의 합을 3으로 나눈 나머지를 추적하면 된다.
이 아이디어를 이용해 DP를 설계할 수 있다.
💡 DP 접근 아이디어
arr[i][r]을 i자리 수 중에서 자리합을 3으로 나눈 나머지가 r인 경우의 수로 정의한다.
(r은 0, 1, 2 중 하나다)
- arr[i][0] → 자리합이 3으로 나누어떨어지는 경우의 수
- arr[i][1] → 자리합을 3으로 나눈 나머지가 1인 경우의 수
- arr[i][2] → 자리합을 3으로 나눈 나머지가 2인 경우의 수
이전 자리 상태(i - 1)에서 1 또는 5를 붙였을 때
자리합의 나머지가 어떻게 변하는지를 이용해 점화식을 세운다.
✅ 결론
끝자리는 항상 5여야 하므로,
마지막 자리(N번째 자리)는 5로 고정된다.
따라서 마지막 자리 바로 전(N - 1번째 자리)까지의 자리합을
3으로 나눈 나머지가 1이어야 한다.
즉, 정답은 arr[N - 1][1]이 된다.
'문제 풀이 > 백준' 카테고리의 다른 글
| [백준] 16472번. 고냥이(Kotlin) (0) | 2025.10.30 |
|---|---|
| [백준] 17352번. 여러분의 다리가 되어드리겠습니다!(Kotlin) (0) | 2025.10.28 |
| [백준] 15553번. 난로(Kotlin) (0) | 2025.10.27 |
| [백준] 16924번. 십자가 찾기(Kotlin) (0) | 2025.10.22 |
| [백준] 24392번. 영재의 징검다리(Kotlin) (0) | 2025.10.21 |