코딩테스트 스터디-1790 수 이어 쓰기2
코딩테스트 스터디-1790 수 이어 쓰기2
ACMICPC 1790 수 이어 쓰기 2
1
2
3
4
5
1부터 N까지의 수를 이어서 쓰면 다음과 같이 새로운 하나의 수를 얻을 수 있다.
>1234567891011121314151617181920212223...
이렇게 만들어진 새로운 수에서, 앞에서 k번째 자리 숫자가 어떤 숫자인지 구하는 프로그램을 작성하시오.
설명
굉장히 해맨 문제였다. GPT의 도움을 받아 겨우 해결할 수 있었는데… 설명하자면 다음과 같다.
- 우선 규칙을 찾아야 한다.
- 일의 자리는 1에서 9까지, 총 9개이다.
- 십의 자리는 10에서 99까지, 총 90*2 = 180개이다.
- 백의 자리도 100에서 999까지 900*3 = 2700개…
- 따라서 각 자리에 해당되는 수는 (자리수)x9x(몇의자리)가 된다!
- N이 2000, k가 1500이고 가정해 보면
- 일단 일의 자리는 9개이니까 넘기고, 십의 자리도 180개니까 넘기는데, 백의 자리는 2700개니까 k는 백의 자리에 있을 것이다.
- 그 다음 k번째 수가 무슨 수인지를 찾으면 된다.
- 사실 이게 가장 어려웠다. 이거를 어떻게 찾는가 말인가…
- 우선 백의 자리니까 3개 단위로 수가 나뉜다. 그리고 1500-180-9=1311 이니까 k는 백의 자리에서 1311번째에 해당되는 수일 것이다.
- 백의 자리니까 100부터 시작할 것이다. 1311-1(일의자리가 0부터 시작하지 않으니까)을 3으로 나눈 몫을 구한다.
1311/3 는 436…2이니까 3단위로 나눈 수의 436번째에 해당된다. 여기에 100을 더해 주면 536, 따라서 k번째 수는 536에 위치한다! - 그 다음에는 마지막으로 이 536에서 몇번째 수인지를 확인해야 한다. 이것도 마찬가지로 1311-1를 3으로 나눈 나머지에 해당될 것이다.
왜 나머지냐면 보통 순서계산에서 몇 번째인지를 구할 때는 몫, 인덱스를 구할 때는 나머지를 구하니까 말이다…–단순 직감–
위에서 계산했을 때 나머지는 2였으니까 536의 2번째 인덱스, 즉 6이 되는 것이다!
- 만약 N이 10이고 k가 11이면..
- 일단 일의자리는 넘었으니까 11-9=2: 십의자리의 2번째
- 십의자리는 2개 단위로 수가 올라가고 10은 제외해야 하니까 (2-1)/2 = 0…1
- 10에 0을 더하면 k가 속한 수는 10, 거기에서 1번째 인덱스니까 0, 따라서 0이 된다!
- 만약에 k-1을 안하면 어떻게 될까?
- 2/2 = 1…0
- 11의 0번째 인덱스니까 0, 이상하게 된다!
정답
아래는 파이썬으로 작성한 코드~
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
N, k = int(input().split())
def solution(N, k):
jari = 1
count = 9 # (자리수) * 9 * (몇의자리) 에서 9 * (몇의자리)
sijak = 1 # (자리수) * 9 * (몇의자리) 에서 (자리수)
# k가 속한 자릿수 구하기
# 자리에 해당되는 개수만큼 계속 빼면서 안넘어갈 때까지
while k > jari * count:
k -= jari * count
jari += 1 # 자리 순번 올려주고
sijak += count # 자리에서 시작할 수도 올리기
count *= 10 # 자리가 올라가니까
# k번째가 어디 수에 속하는지 구하기
# 아까도 말했듯이 k가 아닌 k-1인 이유는 다른 자리는 다 0부터 시작하는데 일의 자리는 1부터 시작하니까
number = sijak + (k - 1) // jari
if number > N:
return -1
# 해당 수에서 인덱스 추출
index = (k - 1) % jari
return int(str(number)[index])
print(solution(n))
후기
지금까지 푼 문제들 중 인상깊은 문제라 올려보았다.
아직도 왜 k가 아닌 k-1인지 정확하게 모르겠다…
This post is licensed under CC BY 4.0 by the author.