题解:CF2082B Floor or Ceil
Statement
给定 \(x,n,m\),每次可以选取进行任意一次如下操作:
- \(x \leftarrow \lfloor\frac{x}{2}\rfloor\)。
- \(x \leftarrow \lceil\frac{x}{2}\rceil\)。
总共进行 \(n\) 次 \(1\) 操作,\(m\) 次 \(2\) 操作,\(n + m\) 次操作不限制顺序,求最终可能得到的 \(x\) 的最小值和最大值。
Solution
贪心。
如果说 \(n\) 足够大,最后最大最小值都会是 \(0\)。
在保持 \(x > 1\) 同时,求最小值我们先尽量消耗 \(m\),再消耗 \(n\),这样一来如果说最后 \(n > 0\) 最小值一定为 \(0\)。
在保持 \(x > 1\) 同时,求最大值我们尽量消耗 \(n\),再消耗 \(m\),这样尽量避免最大值取到 \(0\)。
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
int Test, x, n, m;
inline void Solve() {
scanf ("%lld %lld %lld", &x, &n, &m);
int mnVal = x, mxVal = x, _n = n, _m = m;
while (mnVal > 1 && n + m > 0) {
if (!(mnVal & 1)) {
if (m > 0) m --;
else n --;
mnVal /= 2;
} else {
if (m > 0) {
mnVal = (mnVal / 2) + 1, m --;
} else {
mnVal /= 2, n --;
}
}
}
if (n > 0) mnVal = 0;
n = _n, m = _m;
while (mxVal > 1 && n + m > 0) {
if (!(mxVal & 1)) {
if (n > 0) n --;
else m --;
mxVal /= 2;
} else {
if (n > 0) {
mxVal /= 2, n --;
} else {
mxVal = (mxVal / 2) + 1, m --;
}
}
}
if (n > 0) mxVal = 0;
printf ("%lld %lld\n", mnVal, mxVal);
}
signed main() {
scanf ("%lld", &Test);
while (Test --) Solve();
return 0;
}

浙公网安备 33010602011771号