Codeforces Round #843 (Div. 2)

A - Gardener and the Capybaras

题意

给出字符串S,S只由字符a,b组成,问怎么切分可以使字符串分为小大小,大小大这种的三段。

思路

在2 ~ n - 1的范围内找到字符a的位置,如果里面有a,则将字符a的前半段为a串,a单独为b串,a后c串。此时只有一个a的b串一定是最小的。
如果在范围内未能找到a,则说明全是b,这样将第一个字符为a串,2 ~ n - 1为b串,最后一个字符为c串,此时b串一定是最大的。

void solve() {
	string s;
	cin >> s;
	int n = s.size(), id = -1;
	for (int i = 1; i < n - 1; i ++) {
		if (s[i] == 'a') {
			id = i;
			break;
		}
	}
	
	if (id != -1) {
		cout << s.substr(0, id) << ' ' << 'a' << ' ' << s.substr(id + 1) << endl;
	} else {
		cout << s[0] << ' ' << s.substr(1, n - 2) << ' ' << s[n - 1] << endl;
	}
}

\[\]

B - Gardener and the Array

题意

给出n个数字,每个数字给出二进制位上为1的下标。问这n个数字中是否存在两个子序列或和相等的情况

思路

其实就是找是否存在一个数字完全包括另一个数字,或者说整个集合除了某一个数字的或和包括了这个数字,若是则满足条件。
一开始用的bitset存二进制数字,re了。不明白怎么表示或和,后来发现只需要统计每个数字出现次数即可,若整个数字的二进制位都出现超过两次说明这个数字被别的数字包括

void solve() {
	int n;
	cin >> n;
	map<int, int> mp;
	vector<vector<int>> a(n + 1, vector<int>(0));
	for (int i = 1; i <= n; i ++) {
		int k;
		cin >> k;
		for (int j = 0; j < k; j ++) {
			int x;
			cin >> x;
			a[i].push_back(x);
			mp[x] ++;
		}
	}
	
	for (int i = 1; i <= n; i ++) {
		bool ok = 1;
		for (auto j : a[i]) {
			if (mp[j] < 2) {
				ok = 0;
				break;
			}
		}
		
		if (ok) {
			cout << "YES" << endl;
			return ;
		}
	}
	
	cout << "NO" <<endl;
}

\[\]

C - Interesting Sequence

题意

给出n,x。问是否有n & (n + 1) & (n + 2) & .... & m = x

思路

通过观察即可知道如果n < x 则不可能,等于x直接输出即可,大于x需要判断
手动模拟样例可知,若想让与和等于x,需要消去n上x不存在的二进制为1的数,通过lowbit操作每次找到n的最低位的1,然后模拟进位,若是n可以等于x,则输出,否则若n < x则判负

LL lowbit(LL x) {
	return x & -x;
}
 
//注意观察N的大小
void solve() {
	LL n, x;
	cin >> n >> x;
	if (n < x) {
		cout << -1 << endl;
	}else if (n == x) {
		cout << n << endl;
	}else {
		while (1) {
			LL ans = n + lowbit(n);
			n += lowbit(n);
			n -= lowbit(n);
			if (n == x) {
				cout << ans << endl;
				return ; 
			}
			if (n < x) {
				cout << -1 << endl;
				return ;
			}
		}
	}
}
posted @ 2023-01-11 20:42  nobodyL  阅读(31)  评论(0)    收藏  举报