CF Round 1006 (Div. 3) Problem C 题解

CF Round 1006 (Div. 3) Problem C 题解

题目传送门

萌新第一次写题解, 表达不清请见谅, 本篇题解是想把本人做题时的想法整理下来, 更优秀的题解请移步CF。

本题涉及到 \(MEX\) (在一个整数集合中从 \(0\) 开始第一个没出现的整数), 这种题一般用贪心的方法得到 \(MEX\) 的最大值, 本题也是如此。

分析题目可以得到这样的结论,最终输出的数列可以是从 \(0\) 一直到某个数 \(k\) ,然后在数列的末尾再加上 \(x\) ,但是如果之前的数列进行或运算( \(a|b\) )后已经满足条件,就不用加 \(x\)

这样问题的关键就转换为 \(k\) 是多少, 先考虑 \(n\) 足够大的情况, 对于给定的 \(x\), 把它转换为二进制后, 每一个 \(0\) 位都像是把这一位给占住了, 要输出的数列中的任何一个数转换为二进制后被占住的位都不能是 \(1\), 否则或运算后一定不等于 \(x\)。 顺着这个思路想, 就很容易得到 \(k\) 是怎么算出来的: \(k\) 就是 \(x\) 最低位 \(0\) 之前的 \(1\) 组成的二进制数。 例如,当 \(x = 111011011\) 时, \(k = 11\)。 别忘了现在是在讨论 \(n\) 足够大的情况。

为了避免混淆, 将以上方法求出的 \(k\) 记为 \(k_{max}\)。 当 \(n - 1> k_{max}+1\) 时(为什么是这个条件, 这一点请仔细思考), 前面从 \(0\)\(k_{max}\) 全都占满了, 一共 \(k_{max}+1\) 个数, 数组剩下的长度可以全都填 \(x\)。 再考虑 \(n - 1 \le k_{max}+1\) 的情况, 先对从 \(0\)\(n-1\), 长度为 \(n\) 的数组进行或运算, 如果结果等于 \(x\), 则答案就是从 \(0\)\(n-1\) 数组, 如果不等于 \(x\), 则答案是从 \(0\)\(n-2\) 末尾加上 \(x\)

下面贴上AC代码:

#include <bits/stdc++.h>
using namespace std;

void solve(){
	int n,x;
	cin >> n >> x;
	int k=0,cx=1,xc = x;
	while(x&1){
		k+=cx;
		cx*=2;
		x/=2;
	}
	if(n-1>k+1){
		for(int i=0;i<n;i++){
			if(i<k+1) cout << i << ' ';
			else cout << xc << ' ';
		}
	}else{
		int ans = 0;
		for(int i=0;i<=n-2;i++){
			cout << i << ' ';
			ans |= i;
		}
		if((ans|(n-1))==xc) cout << n-1;
		else  cout << xc;
	}
	cout << endl;
}

int main(){
	int t = 1;
	cin >> t;
	while(t--){
		solve();
	}
}
posted @ 2025-03-09 22:35  古明地恋想睡觉  阅读(59)  评论(0)    收藏  举报