#1 알고리즘
#1-1 직관적인 풀이와 그 한계
#3-1에 있는 50점 짜리 코드는 누구나 생각할만한 직관적인 풀이다. 문제는, L이 큰 경우다. L이 큰 경우는 나머지 연산을 연산 중간 중간에 끼워서 수가 너무 커지지 않게 조절해야 한다. 하지만, 예를 들어 L이 30이라면 3130라는 엄청나게 큰 수를 계산해야하는데 이건 말이 안 된다.
따라서 이 문제는 #3-1에 있는 직관적인 풀이가 아닌 새로운 방식으로 풀어야 한다는 분위기를 풍긴다. 다행히, 문제의 힌트에서 무언가가 보인다.
#1-2 힌트
abcde의 해시 값은 1 × 310 + 2 × 311 + 3 × 312 + 4 × 313 + 5 × 314 = 1 + 62 + 2883 + 119164 + 4617605 = 4739715이다.
반복되는 숫자가 눈에 띈다. 바로 31이다. 대한민국에서 중ㆍ고등학교를 나온 사람이라면 무의식적으로 위 수식을 31 × ( ... )와 같은 형태로 묶고 싶어질 것이다. 나도 그렇다. 한번 묶어 보겠다.
#1-3 괄호 정리
1 × 310 + 2 × 311 + 3 × 312 + 4 × 313 + 5 × 314 =
1 + 31 × (2 × 310 + 3 × 311 + 4 × 312 + 5 × 313) =
1 + 31 × (2 + 31 × (3 × 310 + 4 × 311 + 5 × 312)) =
1 + 31 × (2 + 31 × (3 + 31 × (4 × 310 + 5 × 311))) =
1 + 31 × (2 + 31 × (3 + 31 × (4 + 31 × (5 × 310))))
이렇게 정리하면, 3130과 같은 무식하게 큰 숫자가 나오지 않게 할 수 있다. 또, 아래에 나눠 놓은 ㄱ ~ ㅁ단계처럼 규칙성 있는 형태를 뽑아낼 수 있다.
ㄱ. 31 × (5 + 0)
ㄴ. 31 × (4 + ㄱ)
ㄷ. 31 × (3 + ㄴ)
ㄹ. 31 × (2 + ㄷ)
ㅁ. (1 + ㄹ)
ㄱ단계에서 ㅁ단계까지 가는 규칙성이 눈에 보인다. 이 규칙성을 토대로 코드를 짠다. 각 단계 중간 중간마다 나머지 연산을 잊지 말자.
#2 여담
힌트가 없었으면 꽤 고전했을 것이다. (힌트가 없었다면) 엄청나게 어렵진 않았겠지만, 그렇다고 엄청 쉽지도 않았을 것이다.
#3 코드 - 코틀린
#3-1 50점짜리 코드
import kotlin.math.pow
const val r: Double = 31.0
const val m = 1234567891
fun main() {
// 입력 받기
val l = readln().toInt()
val inputtedAlphabets = readln()
// 계산
var sum = 0.0
for (i: Int in 0..<l) {
val a = inputtedAlphabets[i].code - 96
val powOfR = r.pow(i.toDouble())
sum += a * powOfR
}
// 출력
println((sum % m).toInt())
}
#1-1에서 말한 '직관적인' 코드다. 실제로 백준 사이트에서 50점이라고 출력된다.
#3-2 100점짜리 코드
const val m = 1234567891
fun main() {
// 입력 받기
val l = readln().toInt()
val inputtedAlphabets = readln()
// 계산
var sum: Long = 0
for (i: Int in (l - 1) downTo 0) {
val a = inputtedAlphabets[i].code - 96
sum = if (i == 0) {
sum + a
} else {
31 * (sum + a)
}
sum %= m
}
// 출력
println(sum)
}
sum을 Long이 아닌 Int로 두면, 일정 수 이상의 큰 수부터는 2.4811904E7와 같은 표기법으로 표시해버린다. 따라서 알고리즘이 위 코드와 동일해도 sum의 데이터형이 Int라면 50점이 나온다.
'문제 풀이 > 기타' 카테고리의 다른 글
[백준] 11047 (동전 0) (0) | 2024.11.11 |
---|---|
[백준] 1931 (회의실 배정) (0) | 2024.10.30 |
[백준] 30804 (과일 탕후루) (0) | 2024.06.20 |
[백준] 1764 (듣보잡) (0) | 2024.06.10 |
[백준] 5430 (AC) (0) | 2024.03.07 |