6개의 댓글이 있습니다.
-
-
Taeyoon_Lee -
우왕ㅋ 좋은 방법이네요~
15년 전 link
-
-
-
JongMan -
하드에서 더 좋은 방법은, 에디토리얼에도 나온 방법이지만, 두 가지 경우로 나눠 푸는 것인 것 같아요.
1. 주어진 숫자를 A 라고 할 때, A < B 에 대해서 count(A) == count(B) 인 경우
a. A 와 B 가 첫 자리에서 달라질 때: B 의 해당 자리 수는 A 의 해당 자리수보다 커야 합니다.
b. A 와 B 가 두번째 자리에서 달라질 때: B 의 해당 자리 수는 A 의 해당 자리수보다 커야 합니다.
c.
d. ...
2. B < A 인 경우: 99999...9 를 지나 wraparound 한 경우죠.
두 경우 모두, smallest[i][j] = i개의 segment 를 가지고 만들 수 있는 j자리의 수 중 가장 작은 것은? 이라는 점화식을 풀면 쉽게 풀 수 있죠. 'X 보다 lexicographically larger 중 가장 작은 것 구하기' 스타일의 문제를 풀 수 있는 일반적 패턴인데.. 'X 와 Y 가 달라지는 첫 번째 위치' 를 찾는거죠. 그 전은 X 와 똑같아야 하고, 그 이후는 가능한 가장 작은 수일 테니까요.
15년 전 link
-
-
-
astein -
음.. 제가 연습할 때 푼 방법도 위에서 JM님이 설명해 주신 방법과 완전히 같네요 :$
wraparound인 경우는 첫번째 댓글에 달아뒀던 것처럼 string의 앞에 "2"를 붙여주면 해결이 되고요.
" smallest[i][j] = i개의 segment, j자리의 수 중 가장 작은 것은? " 이라는 문제는 greedy 로 해결 가능한 문제입니다.
k 자리의 digit을 채우는 segment는 최소 2k개, 최대 7k개임을 알 수 있기 때문이죠. 앞자리를 0 ~ 9 까지 채워넣어가면서,
k-1 자리의 digit에서 사용할 수 있는 segment가 2(k-1)이상, 7(k-1)이하인 경우는 앞자리를 고정시킬 수 있으니까요 :3
15년 전 link
-
-
정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.
Taeyoon_Lee
11등한 기념으로(형들이 쓰래서) 에디토리얼을 써보겠습니다.
250, 500, 1000으로 구성된 set이었는데, 그럭저럭 알맞은(?) 난이도였다고 생각합니다.
예상외의 인물이 1등을 했는데, 저도 1등 한번 해보고 싶어요.(?)
Easy (250 pts.)
문제 설명
n*m 격자로 나뉘어져 있는 나무판이 있습니다.
각 격자는 검정(B)색이나 흰(W)색이 칠해져 있습니다.
우리는 8*8 크기로 나무판을 잘라서 체스판을 만들 것입니다.
체스판은 인접한 모든 격자가 서로 다른 색이어야 합니다.
그래서 나무판을 자른 후에, 각 격자에 색칠을 다시해야 하는데,
색칠해야 되는 칸이 최소가 되도록 자르면, 몇 칸을 색칠하면 될까요?
250답게 brute force로 해결할 수 있습니다.
가능한 체스판은 아래와 같이 두종류가 있습니다.
두가지 판을 가능한 모든 위치에 대응해보면서
처음 칠해진 칸과 다른 칸의 개수를 세어보면 됩니다.
Medium (500 pts.)
문제 설명
1페이지부터 N페이지까지 적힌 책이 있습니다. 이 책에 0부터 9까지 각각의 digit는 몇번 등장할까요?
N이 10억이기 때문에 간단한 O(n) 방법은
시간 제한에 걸리게 됩니다. 덕분에 첼 하나 했죠. :)
제 방법은 "10*N의 길이" 정도의 반복으로 풉니다. (결국 O(logN)이죠.)
다른 방법도 있을 것 같은데,
이미 푼 문제는 더 연구하지 않는 게으른 성격 탓에
찾아보진 않았네요.
예를 들어서 설명해볼게요.
123부터 456까지 각각의 디지트의 개수를 구해보죠.
우선 숫자를 늘어놓아 볼까요?
그리고 위 아래에서 숫자를 하나씩 처리합니다. (답에 누적시킵니다.)
시작 숫자의 1의 자리가 0이면 계산을 잠시 멈추고,
마지막 숫자의 1의 자리가 9면 역시 계산을 잠시 멈춥니다.
그리고 위에서부터 숫자를 10개씩 묶어 볼게요.
0으로 시작해서 9로 끝나니까, 딱 맞게 묶이겠죠?
그러면 우선 1의 자리부터 처리합시다.
0~9가 각각 (44-13+1)개가 있습니다. 계산하시구요.
1의 자리를 처리하고나면, 문제는
13부터 44까지 등장하는 각각의 디지트를 세는 문제로 바뀝니다.
물론 곱하기 10을 해서 답을 구해야 겠죠?
Hard (1000 pts.)
문제 설명
매초 1씩 카운트가 증가하는 N자리 숫자 디지털 카운터가 있습니다.
카운터는 숫자가 계속 돕니다. 10^N - 1 다음에 0이 됩니다.
(자리수는 계속 유지되어 999 다음에는 000이 됩니다.)
0부터 9까지 각각의 숫자는 7개 이하의 선분으로 이루어 집니다.
0은 6개, 1은 2개, 2는 5개... 생략 {6,2,5,5,4,5,6,3,7,5}
현재 카운터에 적힌 숫자가 주어집니다.
현재 적힌 숫자를 쓰는데 이용된 선분의 합과,
선분의 합이 같은 숫자가 나오려면 몇 초를 기다려야 될까요?
제가 푼 방식보다 훨씬 좋은 방법이 있는 것 같은데,
역시 이미 pass했기 때문에, 'ㅁ' 굳이 공부하진 않아서,
제 방법을 써보겠습니다.
시간에 쫓기면서 푸느라 코드가 더러워서,
여기에 제 코드 전체를 쓰진 않겠구요,
주요 부분만 보여드리겠습니다.
우선 다이나믹 테이블을 하나 만듭니다.
dy[i][j][k] = 길이 i에서, 선분이 j개 남았을 때, 제일 앞에 k라는 숫자가 올 수 있는가? (있다면 1, 아니면 0)
dy[i][j][k] = dy[i-1][j-su[k]][0~9] 중에 1이 있으면 1, 아니면 0
이걸 구해놓으면 뒷자리부터 하나씩 올려가면서
계산을 해볼 수 있습니다.
예를 들어 현재 숫자가 123456이라고 하면
끝에 6을 7, 8, 9로 하나씩 바꿔가면서 가능 여부를 검사합니다.
6을 쓰는데 이용되는 선분의 수가 6이니까
dy[1][6][7], dy[1][6][8], dy[1][6][9] 중에 1이 있나 검사를 해보고, 있으면 그렇게 바꾸면 됩니다.
하지만 아쉽게도 전부 1이 아닙니다.
그러면 다음 자리로 옮겨와서 5를 하나씩 올려봅니다.
56을 쓰는데 이용된 선분의 수는 11개니까
dy[2][11][6], dy[2][11][7], dy[2][11][8], dy[2][11][9]를 찾아보겠죠.
dy[2][11][6]이 1이겠네요. 그럼 5를 6으로 바꿔주고,
그 뒷자리는 무조건 가능한 가장 작은 수로 써줍니다. 역시 dy배열을 참고해서 해야 겠죠?
dy[1][5][2]가 1일 테니, 처음에 "56"이었던 숫자가 "62"로 바뀌면 되겠군요.
만약 입력이 "11111"나 "71111" 이런 형태면 "99999"가 될 때까지 가능한 답을 찾을 수가 없습니다.
그렇다면 어떻게 하면 될까요?
간단합니다. (하지만 더럽습니다.)
"00000"이 될 때까지 시간이 흘렀다고 생각하고, 그때까지 걸린 시간을 구해놓고, 답을 구하세요.
이때는 전체 성냥 개수를 미리 저장해서 계산해야 되는데..
자세한 코드는 적지 않을게요.
이해가 안 되는 부분 있으면 리플로 알려주세요~
여기까지 읽어주신 분, 감사합니다.
15년 전