D题#小灯做题

题目描述

Tomori在做一个题目,这个题目初始有四个非负整数 a,b,c,k 。

每次Tomori可以对 a,b,c 进行操作:选择其中两个数 x,y,然后将剩下一个数改成 mex(x,y)。

Tomori想知道她最少操作多少次,能让 a,b,c 中的一个数变成 k。若无解,则输出−1。

mex(x,y) 表示最小的非负整数 p ,满足 p≠x 且 p≠y ,例如 mex(1,2)=0,mex(0,2)=1

分析

作为一名蒟蒻,想不出高大上的解法,只能阴暗地打表解决这题

这题的数据范围其实很小,首先判断一开始给的a,b,c有没有直接和k相同的,有就输出0; 如果没有,那么k>=3就不需要再判断,直接输出-1即可,因为题目给出abc3个数,通过mex最多只能创造出0-2(n-1)里的数

接下来就是对k==0,k==1,k==2这三种可能进行分类打表,在打表过程要注意考虑的是a,b,c可能会是重复的数,还有k==2时考虑的情况要分的多一些

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll k,a[3];

void solve() {
	cin>>a[0]>>a[1]>>a[2]>>k;//三个数输入到数组进行排序处理,方便打表
	sort(a,a+3);
	if (a[0]==k or a[1]==k or a[2]==k) { //输入的三个数已经有和k相同的情况
		cout<<0<<'\n';
		return;
	}
	if (k>=3) {//由于没有和k相同的数,那么k>=3直接输出-1
		cout<<-1<<'\n';
		return;
	} else {
		if (k==0) {
			cout<<1<<'\n';//任意两个不为0的数进行mex结果都是0
			return;
		}
		if (k==1) {
			if (a[0]==0) cout<<1<<'\n';//至少有一个0的情况,那么一次就能得到1
			else cout<<2<<'\n';//没有0就得先进行一次mex得到0
			return;
		}
		if (k==2) {
			if (a[2]==0) cout<<2<<'\n';//三个数全为0
			else if (a[2]==1 and a[0]==0) cout<<1<<'\n';//三数有1也有0
			else if (a[0]==1 and a[2]==1) cout<<2<<'\n';//三数全为1
			else if (a[0]>2) cout<<3<<'\n';//三个数全部比2大
			else if (a[1]>2) cout<<2<<'\n';//两个数比2大,那么比2小的数一定是0或者1,所以只需要2次
			else if (a[2]>2 and a[0]!=a[1]) cout<<1<<'\n';//有一个数比2大,另外两数不同(只可能分别是0和1)
			else if (a[2]>2 and a[0]==a[1]) cout<<2<<'\n';//有一个数比2大,另外两数相同(只可能同为0或者同为1)
			return;
		}
	}
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	ll T;
	cin>>T;
	while(T--)
		solve();
	return 0;
}