(BOJ) 1019 책 페이지

1019 책 페이지

  • 분류 : 수학

문제

지민이는 전체 페이지의 수가 N인 책이 하나 있다.

첫 페이지는 1 페이지이고, 마지막 페이지는 N 페이지이다.

각 숫자가 전체 페이지 번호에서 모두 몇 번 나오는지 구해보자.

입력

첫째 줄에 N이 주어진다.

N은 1,000,000,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 0이 총 몇 번 나오는지, 1이 총 몇 번 나오는지, …, 9가 총 몇 번 나오는지를 공백으로 구분해 출력한다.

예제 입력 1

1
11

예제 출력 1

1
1 4 1 1 1 1 1 1 1 1

예제 입력 2

1
7

예제 출력 2

1
0 1 1 1 1 1 1 1 0 0

예제 입력 3

1
19

예제 출력 3

1
1 12 2 2 2 2 2 2 2 2

예제 입력 4

1
999

예제 출력 4

1
189 300 300 300 300 300 300 300 300 300

예제 입력 5

1
543212345

예제 출력 5

1
429904664 541008121 540917467 540117067 533117017 473117011 429904664 429904664 429904664 429904664

Solution

Expander
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
54
55
56
57
58
59
60
import java.util.*

private var N: Int = 0
private var numbers = IntArray(10) { 0 }

fun main() {
input()
solve()
}

private fun input() = with(Scanner(System.`in`)) {
N = nextInt() // 전체 페이지의 수
}

private fun solve() {
var coefficient = 1
var add = 0
while (N != 0) {
val index = N.getFirstDigit() // 1의 자리의 숫자가 타겟
N = N.decrease()

// 0은 일단 제외한다.
numbers[0] -= coefficient

// 0 부터 현재 1의 자리까지 순회
for (j in 0 until index) {
numbers[j] += (N + 1) * coefficient
}

numbers[index] += N * coefficient + 1 + add

// 현재 1의 자리부터 9까지 순회
for (j in index + 1 .. 9) {
numbers[j] += N * coefficient
}

add += index * coefficient
coefficient = coefficient.increase()
}

numbers.forEach {
print("$it ")
}
println()
}

/**
* 1의 자리를 반환한다.
*/
fun Int.getFirstDigit() = this % 10

/**
* 자릿수를 한 칸씩 올린다.
*/
fun Int.increase() = this * 10

/**
* 자릿수를 한 칸씩 내린다.
*/
fun Int.decrease() = this / 10

Point of Thinking

  • 숫자를 나열해놓고 규칙을 찾아야한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    0   10  20 ...
    1 11 21 ...
    2 12 22 ...
    3 13 23 ...
    4 14 24 ...
    5 15 25 ...
    6 16 26 ...
    7 17 27 ...
    8 18 28 ...
    9 19 29 ...

    0 ~ 9까지
    0 1 2 3 4 5 6 7 8 9
    1 1 1 1 1 1 1 1 1 1

    10 ~ 19까지
    0 1 2 3 4 5 6 7 8 9
    1 11 1 1 1 1 1 1 1 1

    20 ~ 29까지
    0 1 2 3 4 5 6 7 8 9
    1 1 11 1 1 1 1 1 1 1
  • 주어진 수를 10으로 나누고, 이 값을 계수로 하여 등장 횟수를 유추할 수 있다.

  • 주어진 숫자의 1의 자리를 기준으로 좌 우를 나눈뒤 계수를 두어 계산해나가면 된다.

  • 10씩 올리고 내리는 등의 반복적인 작업이 많으므로 이를 별도의 함수로 분리해주면 명확해진다.

References