※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 15825번 문제인 System Call이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/15825
15825번: System Call
Linux는 대표적인 유닉스 계열의 운영체제이다. 우리가 잘 아는 macOS 또한 유닉스 계열이다. 이외에도 FreeBSD, NetBSD, Solaris 등이 있다.
www.acmicpc.net
문제의 답이 될 수 있는 버퍼의 크기는 1 이상 50만 이하의 값으로 매우 제한적임을 관찰하자. 따라서 1 이상 50만 이하의 정수 X에 대하여 버퍼의 크기가 X일 때 read를 호출해야 하는 횟수를 알고 있다면 각 버퍼 크기의 경우마다 드는 시간을 직접 조사해보는 것으로 문제를 해결할 수 있게 될 것이다. 이 횟수들을 빠르게 구하는 방법을 설계해보자.
먼저, 크기가 F인 파일 하나에 대하여 버퍼의 크기가 i-1일 때와 i일 때의 필요한 read 호출횟수가 변하는 i값이 무엇인지를 생각해보자. 조금 생각을 해보면 이러한 i값은 오직 O(sqrt(f))개만이 존재함을 알 수 있고, 이를 구해내는 것 또한 O(sqrt(F))의 시간복잡도로 해낼 수 있음을 알 수 있다.
위와 같은 i값들을 모두 구한다면 파일 크기 F에 대하여 i>1인 정수 i에 대해 "버퍼의 크기가 i-1에서 i로 바뀌었을 때 감소하는 read 호출 횟수"를 계산할 수 있게 된다. 각 파일에 대한 이와 같은 자료를 모으면 파일 N개에 대하여 "버퍼의 크기가 i-1에서 i로 바뀌었을 때 감소하는 read 호출 횟수"의 배열(크기 50만)을 만들 수 있게 된다.
위 작업의 시간복잡도는 O(Nsqrt(F)) (N: 파일의 개수, F: 파일의 크기)로, 이는 문제를 해결하기에 충분한 시간복잡도이다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
ll N, T;
ll cnt[500001], C;
ll ans; int ansi = 1;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N;
while (N--) {
int F; cin >> F;
vector<pair<int, int>> vec1, vec2;
int idx = 1;
while (idx * idx < F) {
int y = (F - 1) / idx + 1;
vec1.emplace_back(make_pair(idx, y));
vec2.emplace_back(make_pair(y, idx));
idx++;
}
if (idx * idx == F) vec1.emplace_back(make_pair(idx, idx));
while (!vec2.empty()) {
vec1.emplace_back(vec2.back());
vec2.pop_back();
}
int vsize = vec1.size();
C += vec1[0].second;
for (int i = 1; i < vsize; i++) {
cnt[vec1[i].first] += vec1[i - 1].second - vec1[i].second;
}
}
cin >> T;
ans = (T + 1) * C;
for (ll i = 2; i < 500001; i++) {
C -= cnt[i];
ll tmp = (T + i) * C;
if (tmp < ans) ans = tmp, ansi = i;
}
cout << ans << ' ' << ansi;
}
'BOJ' 카테고리의 다른 글
[BOJ 2897 // C++] 몬스터 트럭 (0) | 2023.08.21 |
---|---|
[BOJ 15823 // C++] 카드 팩 구매하기 (0) | 2023.08.21 |
[BOJ 4117 // C++] Combination Lock (0) | 2023.08.19 |
[BOJ 15826 // C++] Namje Adventure (0) | 2023.08.19 |
[BOJ 15831 // C++] 준표의 조약돌 (0) | 2023.08.18 |