Educational Codeforces Round 144 (Rated for Div. 2) - C. Maximum Set (1600)
단순히 에 대해 를 검사한다.
을 넘어가기 직전이 최대로 얻을 수 있는 개수이다.
그런데 첫 예시를 보면 알 수 있듯 같은 경우도 배제할 수 없다.
그러나 그 다음에 이상이 곱해질일은 절대없다.
그러면 를 두 번 곱하는 걸로 대체되어 집합의 원소 개수가 더 늘어나기 때문이다.
한가지 더, 은 두 번 곱해질 일이 없다.
이 곱해지는 타이밍은 상관이 없다.
이든 든 똑같다.
이 두 번이상 곱해지면 가 되어 이 되어서 를 계속 곱한것보다 원소수가 같아질 일이 없다.
을 두 번 곱한것보다 를 세 번 곱한것이 더 수가 안커지고 집합 원소 개수가 늘어나기 때문이다.
따라서 에서 먼저 만 계속 곱해서 최대 개수가 나오는 범위 를 찾은다음에
거기서 을 한 번 곱해도 최대 개수가 나오는 범위 를 찾는다.
정답 집합의 개수가 라면 번의 연산중에 을 끼워넣거나 아니면 만 써서 할 수 있으므로
가 정답이다.
void solve() {
int l, r;
cin >> l >> r;
auto C = [&](int i) {
int ret = 0;
int c = i;
while (c <= r) {
ret++;
c *= 2;
}
return ret;
};
auto C3 = [&](int i) {
int ret = 0;
int c = i;
while (c <= r) {
ret++;
if (i == c) c *= 3;
else c *= 2;
}
return ret;
};
int ans1 = C(l), ans2 = 0;
cout << ans1 << ' ';
int lo = l, hi = r, ret3 = -1, ret2 = -1;
while (lo <= hi) {
int m = lo + hi >> 1;
if (C3(m) == ans1) ret3 = m, lo = m + 1;
else hi = m - 1;
}
lo = l, hi = r;
while (lo <= hi) {
int m = lo + hi >> 1;
if (C(m) == ans1) ret2 = m, lo = m + 1;
else hi = m - 1;
}
if (ret3 == -1) {
cout << ret2 - l + 1;
} else {
int cnt3 = ret3 - l + 1;
int cnt2 = ret2 - l + 1 - cnt3;
ans2 = cnt2;
ans2 = md(ans2 + ans1 * cnt3);
cout << ans2;
}
cout << endl;
}
Comments