이번 문제는 k의 범위가 매우 크기 때문에 k를 최대한 줄인 뒤에 이진수로 표현하는 방식으로 수를 표현하고 이를 4와 7로 변환시켜 해결하였다. 전체적인 풀이의 이해를 위한 설명은 다음과 같다.
- 자리수가 1인 경우는 2가지, 2인 경우는 4가지, 3인 경우는 8가지, ... 이므로 자리수가 n일 때에 2^n가지가 존재하는 것을 알 수 있다.
- n을 먼저 구하고, k+1에서 2^n을 빼주면 구하고자 하는 수를 구할 수 있다. 이를 설명하기 위해 먼저 이진수로 표현하는 방법부터 설명한다.
-> num이라는 수가 있을 때, 이를 이진수로 표현하기 위해서는 이 수가 0이 될 때까지 2로 나누고 그 나머지를 역순으로 나열한다.
ex) 7%2=1, 3%2=1, 1%1=1. => 111(2).
- 4와 7 두가지 수만 주어졌으므로 이진수표현법과 같이 구현할 수 있다. 0은 4로, 1은 7로 대입한다.
- k+1에서 2^n을 2로 나누고 이의 나머지를 취하는 과정을 n만큼 반복하면 정답의 역순으로 이루어진 배열을 얻을 수 있게 된다.
코드는 다음과 같이 작성하였다.
- k를 입력받는다.
- n을 구하기 위해 2^?의 누적합을 구해야한다. 누적합을 위한 변수 cnt를 0으로 정의한다.
- 자리수를 저장할 변수 n을 0으로 정의한다.
- 이진수로 표현된 수를 저장할 배열 answer를 선언한다.
- 정답을 저장할 변수 result를 string형으로 선언한다.
- while문을 돌린다.
-> n을 1 증가시킨다.
-> cnt에 2^n을 더한다.
-> 만약 cnt가 k보다 크거나 같을 경우 while문을 종료한다.
- 최소로 줄인 k를 저장할 변수 idx를 선언하고 idx를 k-2^n+1로 정의한다.
- 정답은 n의 자리수이므로 n번 반복하는 i에 대한 for문을 돌린다.
-> answer에 idx%2를 넣는다.
-> idx를 2로 나눈 값으로 갱신한다.
- answer를 역순으로 정렬한다.
- answer의 길이만큼 반복하는 i에 대한 for문을 돌린다.
-> 만약 answer[i]가 1이라면 result에 7을 붙인다.
-> 만약 answer[i]가 0이라면 result에 4를 붙인다.
- result는 string형이므로 int형으로 바꾸어 출력한다.
Code
k=int(input())
cnt=0
n=0
answer=[]
result=''
while 1:
n+=1
cnt+=2**n
if cnt>=k:
break
idx=k-2**n+1
for i in range(n):
answer.append(idx%2)
idx//=2
answer.reverse()
for i in range(len(answer)):
if answer[i]==1:
result+='7'
else:
result+='4'
print(int(result))