반응형
https://www.acmicpc.net/problem/1790
본 문제는 1 ~ n 까지의 수를 이어서 썼을 때 길이를 구하고 k의 위치의 값을 출력하는 문제다. n의 최대값이 매우 크기 때문에 실제로 값을 구해서 찾는 것은 불가능 하다. 따라서, k와 인접한 위치를 찾아서 출력하는 방식을 이용해야 한다. 이때, 이분 탐색을 이용하면 빠르게 답을 구할 수 있다. 예를 들어 n = 20 일 때,
- 우선 n까지의 길이가 k보다 짧을 경우를 예외처리 한다.
- 1 ~ 9 까지의 길이를 구하고 10 ~ 20까지의 길이를 구한다.
- 그리고 k에 인접한 수를 찾는다.
- k 보다 작은 수를 구하도록 코딩을 하였다.
- 그렇기 때문에 k 보다 커지는 순간까지 추가로 구해야 한다.
- 이제 내가 찾아야하는 위치는 인접한 수의 길이에서 k보다 작은 길이를 빼고
- 찾아야 하는 위치을 더하면 된다.
- 이때, 배열의 인덱스를 생각하면서 추가로 1을 뺀다.
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #include <cstdio> #include <string> using namespace std; int n; long long k; int ans; long long cal_length(int x) { // 1 ~ 9 : 9 * 1 // 10 ~ 99 : 90 * 2 // 100 ~ 999 : 900 * 3 // .... long long n_length = 0LL; long long n_size = to_string(x).size(); for (long long add = 9LL, len = 1LL; len < n_size; add *= 10, len += 1) { n_length += add*len; } int start = 1; // ~ n for (int i = 1; i < n_size; i++) { start *= 10; } return n_length += n_size * (x-start+1); } void cal (int start, int end) { if (start >= end) return; int mid = (start + end) / 2; if (cal_length(mid) > k) { cal(start, mid-1); } else { ans = mid; cal(mid+1, end); } } int main() { scanf("%d %lld", &n, &k); long long n_length = cal_length(n); if (n_length < k) { printf("-1\n"); return 0; } cal(1, n); long long ans_length = cal_length(ans); string s = to_string(ans); // (ans_length < k) to // (k < ans_length) while (ans_length < k) { ans += 1; s += to_string(ans); ans_length += to_string(ans).size(); } printf("%c\n", s[s.size() - ans_length + k) - 1]); } | cs |
반응형
'백준' 카테고리의 다른 글
[백준 11725] 트리의 부모 찾기 (0) | 2020.02.10 |
---|---|
[백준 6087] 레이저 통신, C++ (0) | 2020.02.07 |
[백준 11728] 배열 합치기, C++ (0) | 2020.02.05 |
[백준 10816] 숫자 카드 2, C++ (0) | 2020.02.05 |
[백준 17089] 세 친구, C++ (0) | 2020.02.04 |
댓글