专栏文章

二进制与一 II 题解

P11968题解参与者 15已保存评论 15

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
15 条
当前快照
1 份
快照标识符
@miqei54f
此快照首次捕获于
2025/12/04 03:29
3 个月前
此快照最后确认于
2025/12/04 03:29
3 个月前
查看原文
出题人题解。
问题可以转换为求比 xx 小的在二进制下有 kk 位为 11 的最大的 aa,及比 xx 大的在二进制下有 kk 位为 11 的最小的 bb,答案则为 min(xa,bx)\min(x-a,b-x)
既然有大小关系的比较,那不妨枚举从最高位开始,a,ba,b 分别在哪一位与 xx 不同。假设当前考虑到第 ii 位(从右往左数),那么对于 aa 来说,xx 在二进制下,该位必须为 11,此时 aa 此位便为 00,且由于我们应当构造出最大的合法的 aa,所以 aa 从第 i1i-1 位开始应当是一段连续的 11bb 同理,应贪心的将 11 尽量放在靠右的位上。

Code

CPP
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[65], t;

int sum(int x) {
	int ans = 0;
	while (x) {
		ans += x % 2;
		x /= 2;
	}
	return ans;
}

signed main() {
	int T;
	cin >> T;
	while (T--) {
		int n, k;
		cin >> n >> k;
		int x = n;
		if (sum(n) == k) {
			cout << 0 << "\n";
			continue;
		}
		t = 0;
		while (x) {
			a[++t] = x % 2;
			x /= 2;
		}
		if (t <= k)
			cout << (1LL << k) - 1 - n << "\n";
		else {
			int now = 0, one = 0, ans = (1LL << t) + (1LL << (k - 1)) - 1 - n;
			for (int i = t; i >= 1; i--) {
				bool e = (n & (1LL << i - 1));
				if (e) {
					int tmp = now * 2;
					if (i - 1 < k - one || one > k)
						continue;
					tmp *= (1LL << i - 1);
					tmp += (1LL << (i - 1)) - 1 - ((1LL << (i - 1 - (k - one))) - 1);
					one++;
					ans = min(ans, n - tmp);
				}
				now = now * 2 + e;
			}
			now = 0, one = 0;
			for (int i = t; i >= 1; i--) {
				bool e = (n & (1LL << i - 1));
				if (e)
					one++;
				else {
					int tmp = now * 2 + 1;
					if (i - 1 < k - one - 1 || one >= k)
						continue;
					tmp *= (1LL << i - 1);
					if (k - one - 1)
						tmp += (1LL << (k - one - 1)) - 1;
					ans = min(ans, tmp - n);
				}
				now = now * 2 + e;
			}
			cout << ans << "\n";
		}
	}
}

评论

15 条评论,欢迎与作者交流。

正在加载评论...