题解:CF2082B Floor or Ceil

Statement

给定 \(x,n,m\),每次可以选取进行任意一次如下操作:

  1. \(x \leftarrow \lfloor\frac{x}{2}\rfloor\)
  2. \(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;
}
posted @ 2025-03-17 15:05  xAlec  阅读(117)  评论(0)    收藏  举报