比赛链接:

https://codeforces.com/gym/103427
https://ac.nowcoder.com/acm/contest/24346

B. Bitwise Exclusive-OR Sequence

题意:

给定 \(m\) 个限制,要求构造一个全是非负整数的序列 \(a\),每个限制告诉 \(u, v, w\),要求满足 \(a_u\) ^ \(a_v\) = \(w\),如果能构造出来,要求输出构造出的 \(a\) 序列的所有元素总和的最小值,否则输出 -1。

思路:

可以构建一个图,让 \(u, v\) 之间有一条权重为 \(w\) 的边。接着对整个图进行染色,对于一个数字,每一位只可能是 0 或者 1,选择一个未染色的点(记为起点)将它标为 0,即该点每一位都是 0,修改所有连通的点,如果有不符合限制的点出现,输出 -1,否则可以染好颜色。
对于每一位,只可能有两种情况,刚开始将起点染为了 0,另一种情况就是起点为 1,两种情况取一个 1 少的,即是该位上之和的最小值。

代码:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int n, m;
	cin >> n >> m;
	vector < vector < pair <int, int> > > e(n + 1);
	for (int i = 0; i < m; i ++ ){
		int u, v, w;
		cin >> u >> v >> w;
		e[u].push_back({w, v});
		e[v].push_back({w, u});
	}
	LL ans = 0;
	vector <int> c(n + 1, -1);
	for (int i = 1; i <= n; i ++ ){
		if (c[i] == -1){
			vector <int> a;
			function<void(int)> dfs = [&](int u){
				a.push_back(c[u]);
				for (auto [w, v] : e[u]){
					if (c[v] == -1){
						c[v] = c[u] ^ w;
						dfs(v);
					}
					else if ((c[u] ^ c[v]) != w){
						cout << "-1\n";
						exit(0);
					}
				}
			};
			c[i] = 0;
			dfs(i);
			for (int i = 0; i < 30; i ++ ){
				LL cnt = 0;
				for (auto j : a)
					cnt += (j >> i) & 1;
				ans += min(cnt, (LL)a.size() - cnt) * (1 << i);
			}
		}
	}
	cout << ans << "\n";
	return 0;
}

E. Edward Gaming, the Champion

题意:

给定字符串,求 "edgnb" 子串出现的数量。

思路:

按题意模拟。

代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	string s;
	cin >> s;
	int cnt = 0;
	for (int i = 0; i < (int)s.size() - 4; i ++ )
		cnt += (s.substr(i, 5) == "edgnb");
	cout << cnt << "\n";
	return 0;
}

F. Encoded Strings I

题意:

定义 \(F(c) = chr(G(c, s))\)\(G(c, s)\) 表示在字符串 \(s\) 中最后一个 \(c\) 位置之后有几个不同的字母,\(chr(i)\) 表示第 \(i + 1\) 个字母,现在给定一个字符串,问它的所有前缀通过 \(F(c)\) 转化后的最大字典序是什么。

思路:

直接暴力跑出所有前缀转化后的字符串,然后排个序就行。

代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int n;
	cin >> n;
	string s;
	cin >> s;
	auto get = [&](string t){
		vector <int> pos(26, -1);
		int m = t.size(), cnt = 0;
		for (int i = m - 1; i >= 0; i -- ){
			if (pos[t[i] - 'a'] != -1) continue;
			pos[t[i] - 'a'] = (cnt ++ );
		}
		string ans = "";
		for (int i = 0; i < m; i ++ )
			ans = ans + (char)('a' + pos[t[i] - 'a']);
		return ans;
	};
	vector <string> a;
	for (int i = 1; i <= n; i ++ )
		a.push_back(get(s.substr(0, i)));
	sort(a.begin(), a.end());
	cout << a[n - 1] << "\n";
	return 0;
}

J. Luggage Lock

题意:

有一个四位数的密码锁,每次可以将连续的几位同时向上或者向下转动,现在有 \(q\) 次询问,问将密码锁从 \(a\) 状态变成 \(b\) 状态最少需要几步。

思路:

通过 \(bfs\) 预处理出所有情况,然后每次 \(O(1)\) 回答询问即可。

代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	vector <int> d(10000, -1);
	d[0] = 0;
	auto bfs = [&](){
		queue <int> q;
		q.push(0);
		while(!q.empty()){
			auto u = to_string(q.front());
			q.pop();
			while((int)u.size() < 4) u = '0' + u;
			for (int i = 0; i < 4; i ++ ){
				for (int j = i; j < 4; j ++ ){
					auto t = u;
					for (int k = i; k <= j; k ++ )
						t[k] = (t[k] - '0' + 1) % 10 + '0';
					if (d[stoi(t)] == -1){
						d[stoi(t)] = d[stoi(u)] + 1;
						q.push(stoi(t));
					}
					t = u;
					for (int k = i; k <= j; k ++ )
						t[k] = (t[k] - '0' + 9) % 10 + '0';
					if (d[stoi(t)] == -1){
						d[stoi(t)] = d[stoi(u)] + 1;
						q.push(stoi(t));
					}
				}
			}
		}
	};
	bfs();
	int T;
	cin >> T;
	while(T -- ){
		string a, b;
		cin >> a >> b;
		for (int i = 0; i < 4; i ++ )
			b[i] = (b[i] - a[i] + 10) % 10 + '0';
		cout << d[stoi(b)] << "\n";
	}
	return 0;
}
posted on 2022-10-07 19:47  Hamine  阅读(65)  评论(0编辑  收藏  举报