관리 메뉴

Bull

[백준] 1019: 책 페이지 (C++) 본문

Algorithm/Baekjoon

[백준] 1019: 책 페이지 (C++)

Bull_ 2024. 9. 22. 12:31

문제


1019: 책 페이지
N이 36이라면 1~36페이지까지 즉 1,2,3,...35,36에 나오는 모든 숫자를 다 세는 것이다.

설명


각 자리 수 마다 검사하여 모든 경우의 수를 구한다. 1234라는 N이 주어졌을 때 1,2,3,4 모두 검사하는 것이다.

1의 자리 수를 검사할 때 1의 자리를 0~9까지 모두 바꿔보는 것이다. 그리고 일의 자리를 제외한 나머지 부분을 보는 것이다.

주석을 보고 숫자 디버깅으로 이해하는 게 편할 것이니 포괄적인 설명은 포기한다. (포괄적으로 말하기가 어려워서)

1204일 때 0104~1204 (0004는 불가, 다른 숫자 과정에서 겹침.)
1214일 때 0014~1214
1224일 때 0024~1224
1234일 때 0034~1134 | 1230,1231,1232,1233,1234
1244일 때 0044~1144
1254일 때 0054~1154
1264일 때 0064~1164
1274일 때 0074~1174
1284일 때 0084~1184
1294일 때 0094~1194

만약 검사 자리 수가 0이라면 (1204에서 십의 자리를 검사)
나머지 검사는 똑같음. d=0로 될 때만 보자면
1204일 때 0104~1104 | 1200,1201,1202,1203,1204

원본이 1234인 애가 1204를 검사할 때 01부터 시작하는 것은 같지만 오른쪽 수에 대한 경우는 계산하지 않았다. 왜냐하면 원본 십의 자리 3이 0보다 컷기 때문에 오른쪽 수에 대해서 0~9까지 모두 유효했기 때문이다.

1019: CODE


#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

typedef long long ll;
typedef vector<ll> vec1;
typedef vector<vec1> vec2;
typedef vector<vec2> vec3;
vec1 cnt(10, 0);

void init() {
    cin.tie(NULL);
    cout.tie(NULL);
    ios::sync_with_stdio(false);
}

void countDigits(ll n) {
    // 1, 10, 100, ...
    ll factor = 1;

    while (n / factor != 0) {
        // n=3564, factor=1
        // higher=356, current=4, lower=0
        // n=3564, factor=10
        // higher=35, current=6, lower=4
        // n=3564, factor=100
        // higher=3, current=5, lower=64
        // n=3564, factor=1000
        // higher=0, current=3, lower=564

        // 현재 자릿 수보다 높은 자릿 수 (왼쪽)
        ll higher = n / (factor * 10);
        // 현재 자릿 수
        ll current = (n / factor) % 10;
        // 현재 자릿 수보다 낮은 자릿 수 (오른쪽)
        ll lower = n % factor;

        // 관찰 자리수를 0부터 9까지 증가시키면서 카운트
        for (int d = 0; d < 10; d++) {
            if (d != 0) {
                if (current > d) {
                    // n=3564, factor=10, d=1,2,3,4,5
                    // 0014~3514: (35+1)*10
                    // 0024~3524: (35+1)*10
                    // 0034~3534: (35+1)*10
                    // 0044~3544: (35+1)*10
                    // 0054~3554: (35+1)*10
                    // 10의 자리가 1,2,3,4,5인 경우에서
                    // 그 10의자리에 나오는 숫자의 개수를 세겠다는 의미임.
                    // 다른 factor검사에서 중복된 전체 숫자가 나올 순 있지만
                    // 자리수의 숫자를 세는 것이므로 중복은 상관없음.
                    cnt[d] += (higher + 1) * factor;
                } else if (current == d) {
                    // d=6, lower=4, higher=35, factor=10
                    // 0064~3564: 35*10+4+1
                    // 즉 0064~3464까지 35*10개의 숫자가 나오고
                    // 3560~3564까지 4+1개의 숫자가 나옴.
                    // 왜 3564가 안되냐면 그 이전에 3554같은 경우는 lower가
                    // 1의 자리 수인 경우 0,1,2,...,9까지 다 되는데
                    // 3564는 4까지만 되기 때문임.
                    cnt[d] += higher * factor + lower + 1;
                } else {
                    // n=3564, factor=10, d=7,8,9
                    // 0074~3474: 35*10
                    // 0084~3484: 35*10
                    // 0094~3494: 35*10
                    cnt[d] += higher * factor;
                }
            } else {
                if (higher == 0) {
                    // 첫 자릿수에서 0은 카운트하지 않음
                    continue;
                }
                if (current > 0) {
                    // d=0, higher=35, factor=10,current=6
                    // d=0이면 오른쪽 첫자리가 0으로 시작할 수 없음
                    // 0104~3504:

                    cnt[0] += higher * factor;
                } else if (current == 0) {
                    // n=3504 factor=10라고할 때
                    // 0104~3404: 34*10
                    // 3500,3501,3502,3503,3504: 5개
                    cnt[0] += (higher - 1) * factor + lower + 1;
                }
            }
        }

        factor *= 10;
    }
}
int main() {
    init();
    int N;
    cin >> N;
    countDigits(N);
    for (int i = 0; i < 10; i++) {
        cout << cnt[i] << " ";
    }
    return 0;
}

'Algorithm > Baekjoon' 카테고리의 다른 글

[백준] 2143: 두 배열의 합 (C++)  (10) 2024.07.22
[백준] 1806: 부분합 (C++)  (0) 2024.07.20
[백준] 13913: 숨바꼭질 4 (C++)  (0) 2024.05.19
[백준] 9019: DSLR (C++)  (0) 2024.05.16
[백준] 14502: 연구소 (C++)  (0) 2024.05.14