https://www.acmicpc.net/problem/2023
2023번: 신기한 소수
수빈이가 세상에서 가장 좋아하는 것은 소수이고, 취미는 소수를 가지고 노는 것이다. 요즘 수빈이가 가장 관심있어 하는 소수는 7331이다. 7331은 소수인데, 신기하게도 733도 소수이고, 73도 소수
www.acmicpc.net
난이도 : 골드 5
태그 : 수학, 정수론, 백트래킹, 소수 판정
설명
백트래킹 + 소수판정 문제입니다.
백트래킹으로 수열을 구한 뒤, 수열을 숫자로 바꿔 해당 숫자가 소수인지 판단하였습니다.
소스코드
시간초과
var n = -1
lateinit var nums: Array<Int>
val sb = StringBuilder()
fun main() {
n = readln().toInt()
nums = Array(n) { -1 }
backTracking(0)
print(sb)
}
fun backTracking(depth: Int) {
if (depth == n) {
if (nums[n - 1] % 2 != 0 && isPrime(depth - 1)) sb.append(nums.joinToString("")).append("\n")
return
}
val start = if (depth == 0) 2 else 0
for (i in start until 10) {
nums[depth] = i
if (isPrime(depth)) backTracking(depth + 1)
}
}
fun isPrime(idx: Int): Boolean {
var sum = 0
for (i in 0..idx) {
sum = sum * 10 + nums[i]
for (j in 3 until sum) {
if (sum % j == 0) return false
}
}
return true
}
하지만 시간초과가 났습니다.
소수의 자리수는 최대 8개로, 10 ^ 8 까지입니다. 네... 모든 수열을 다 체크하니까 시간초과 날만했네요.
안되면 미리 쳐내기
lateinit var nums: Array<Int>
var n = -1
val sb = StringBuilder()
fun main() {
n = readln().toInt()
nums = Array(n) { -1 }
backTracking(0)
print(sb)
}
fun backTracking(depth: Int) {
if (depth == n) {
if (isPrime(depth - 1)) sb.append(nums.joinToString("")).append("\n")
return
}
val start = if (depth == 0) 2 else 0
for (i in start until 10) {
nums[depth] = i
if (isPrime(depth)) backTracking(depth + 1)
}
}
fun isPrime(idx: Int): Boolean {
var sum = 0
for (i in 0..idx) {
sum = sum * 10 + nums[i]
for (j in 2 until sum) {
if (sum % j == 0) return false
}
}
return true
}
1000 ~ 1999는 1이 소수가 아니기 때문에 1으로 시작하는 숫자는 찾을 필요가 없습니다.
2의 배수인 4, 6, 8로 시작하는 숫자 역시 찾을 필요가 없죠.
즉, 백트래킹을 할 때마다 어차피 안되는 수들은 미리 쳐내는 방법으로 시간초과를 해결할 수 있었습니다.
후기
백트래킹은 언제해도 재밌습니다. 짜릿합니다. 너무 좋아.
'코딩테스트 > Kotlin' 카테고리의 다른 글
[백준 10102번] [Kotlin] 개표 (0) | 2023.03.31 |
---|---|
[백준 2557번] [Kotlin] Hello World (0) | 2023.03.31 |
[백준 15351번] [Kotlin] 인생 점수 (0) | 2023.03.29 |
[백준 11047번] [Kotlin] 동전 0 (0) | 2023.03.29 |
[백준 4458번] [Kotlin] 첫 글자를 대문자로 (0) | 2023.03.29 |