https://www.acmicpc.net/problem/1790
1790번: 수 이어 쓰기 2
첫째 줄에 N(1 ≤ N ≤ 100,000,000)과, k(1 ≤ k ≤ 1,000,000,000)가 주어진다. N과 k 사이에는 공백이 하나 이상 있다.
www.acmicpc.net
이분탐색
#include <iostream>
#include <string>
using namespace std;
// 1부터 N까지 수를 이어붙인 길이 구하기
long long cal_length(int N)
{
	long long len = 0;
	for (int start = 1, i = 1; start <= N; start *= 10, ++i)
	{
		int end = start * 10 - 1;
		if (end > N)
		{
			end = N;
		}
		len += (long long)(end - start + 1) * i;
	}
	return len;
}
int binary_search(int left, int right, int target)
{
	if (left >= right)
	{
		return right;
	}
	int mid = (left + right) / 2;
	long long len = cal_length(mid);
	/*
		1부터 mid까지 이어붙인 수의 길이 < target 이면
		[mid + 1, right] 범위에서 재 탐색
	*/
	if (len < target)
	{
		return binary_search(mid + 1, right, target);
	}
	/*
		1부터 mid까지 이어붙인 수의 길이 >= target 이면
		[left, mid] 범위에서 재 탐색 (mid값 포함)
	*/
	else
	{
		return binary_search(left, mid, target);
	}
}
int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	// 입력
	int N, K;
	cin >> N >> K;
	// 수의 길이가 K보다 작은 경우
	if (cal_length(N) < K)
	{
		cout << -1;
		return 0;
	}
	// 1부터 num까지 이어붙였을 때의 길이가 K보다 같거나 큰 최소의 수 num구하기
	int num = binary_search(1, N, K);
	// 1부터 num까지 이어붙였을 때의 길이 num_len구하기
	int num_len = cal_length(num);
	
	string s_num = to_string(num);
	// num에서 뒤에서 (num - K)만큼 앞에 있는 숫자 구하기
	cout << s_num[(s_num.size() - 1 - (num_len - K))];
	return 0;
}
1부터 N까지의 수를 이어서 쓰면 다음과 같이 새로운 하나의 수를 얻을 수 있다.
1234567891011121314151617181920212223...
이렇게 만들어진 새로운 수에서, 앞에서 k번째 자리 숫자가 어떤 숫자인지 구하는 프로그램을 작성하시오.
풀이과정은 다음과 같다.
1. 1부터 num까지 이어붙인 수의 길이 num_len이 K보다 같거나 큰 최소의 수 num을 구한다.
2. num_len과 K의 차이를 구해 K번째 수를 구한다.
1번 과정에서 이분탐색을 활용한다.
수의 길이를 구할때의 시간복잡도는 O(N의 길이)이고
이분탐색의 시간복잡도가 O(log N)이기 때문에 시간제한에 걸리지 않고 풀이할 수 있다!
이분탐색을 참고한 블로그
이진 탐색과 시간 복잡도 분석 (Binary Search and its Time Complexity Analysis)
오늘 다뤄 볼 주제는 바로 "이진 탐색(Binary Search)" 입니다. 높은 효율을 자랑하며 실제로 자주 쓰이는 알고리즘인데요, 과연 이진 탐색이라는 게 무엇인지 한번 알아봅시다! - 이진 탐색(Binary Searc
jwoop.tistory.com
'Algorithm > BOJ' 카테고리의 다른 글
| [BOJ]10816번: 숫자 카드 2 (c++) (0) | 2020.07.07 | 
|---|---|
| [BOJ]10815번: 숫자 카드 (c++) (0) | 2020.07.07 | 
| [BOJ]1377번: 버블 소트 (c++) (0) | 2020.07.07 | 
| [BOJ]11652번: 카드 (c++) (0) | 2020.07.07 | 
| [BOJ]2751번: 수 정렬하기 2 (c++) (0) | 2020.07.06 | 
댓글