입력이 1,000,000,000까지 들어온다. 10억이 넘기때문에 O(N)으로 문제를 풀어도 시간 복잡도가 초과된다. 당연히 숫자 하나씩 정수를 세는 방법은 실행 시간 초과 때문에 불가능하다.
입력 값이 굉장히 크기 때문에 이럴 땐 다른 방식으로 접근해야한다. 원래는 자리수 n에 따른 공식을 세워서 일반화하려고 했으나, 0이 맨 앞자리에 있을땐 날라가는 문제 때문에 다른 방식으로 처리를 했다.
그래서 각 자릿수 별로 0-9가 몇번씩 등장하는지 확인하는 것이 더 쉬울 것 같아서 그 방식으로 구현하고자 했다. 따라서 문자열로 숫자를 입력받아서 앞자리를 하나씩 자른다. 방법은 다음과 같다.
ex) 백준 예제입력 5의 N = 543212345를 이용해 설명하겠다.
5보다 작은 수들은 1,2,3,4는 5의 자릿수만큼 나왔다는 뜻이고 5는 5의 뒤의 수만큼 나온것을 의미한다. 이 때 반복문은 그냥 0~4까지 실행되도록 하고 마지막에 0을 빼주는 방식으로 진행했다. (맨 앞자리에 0은 올 수 없다.)
- '1'00000000 ~ '1'99999999 이므로 1은 나온 것이며 이는 2, 3, 4도 동일하다.
- 5는 '5'000000000 ~ '5'43212345이므로 5는 '5'를 뺀 뒤 나머지 숫자만큼, 여기서는 43212345번 나온다는 것을 알 수 있다.
000 ~ 999 꼴의 수열에서 정수의 개수는 자리수를 k라고 했을때 다음 공식을 만족한다.
import sys
input = sys.stdin.readline
n = input().strip()
ans = [0] * 10
k = len(n)
for x in n: #1번이자 5번과정 for문을 자릿수를 내려가면서 진행
k -= 1 #자리수의 위치
for i in range(int(x)):
ans[i] += 10**k #2번 과정
for j in range(10):
if k >= 1: #k가 1의자리 이상일 때만 하도록 처리
ans[j] += (10 ** (k - 1)) * k #3번 과정
ans[0] -= 10**k #4번 과정
if k:
ans[int(x)] += int("".join(n[-k:])) + 1 #5번 과정
else:
#k=0이면 지금 1의자리 숫자 진행중이므로 뒤의 숫자가 더 없으므로 그냥 내 자리 숫자만 더해준다.
ans[int(x)] += 1
print(*ans)