Codeforces Round #624 (Div. 3)解题报告

Codeforces Round #624 (Div. 3)

【A.Add Odd or Subtract Even】

【题目大意】
给你两个正整数a和b,每次你可以选择将a加上一个奇数或者将a减去一个偶数,问你操作多少次后可以将a变成b

【解题思路】
如果a = b显然答案为0
如果a < b:
如果(b - a) % 2 == 0,那么我们可以将a加至b + 1然后再减去1,答案为2
否则直接让a加到b,答案为1
如果a > b:
如果(a - b) % 2 == 0,那么我们直接让a减至b,答案为1
否则我们将a减至b - 2然后再加上2,答案为2

【AC代码】

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		int a, b;
		cin >> a >> b;
		int ans = 0;
		if (a < b) {
			if ((b - a) & 1) ans = 1;
			else ans = 2;
		}
		else if(a > b){
			if ((a - b) & 1) ans = 2;
			else ans = 1;
		}
		cout << ans << endl;
	}
	return 0;
}

【B.WeirdSort】

【题目大意】
给你数组a和数组p,你可以将a[p[i]]与a[p[i] + 1]交换,问你经过有限次交换使得数组a非降序排列

【解题思路】
考虑交换排序的思想,如果ai > aj那么我们看p数组中i - j是否均存在

【AC代码】

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
int a[110];
bool p[110];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		int n, m;
		cin >> n >> m;
		memset(p, false, sizeof(p));
		for (int i = 1; i <= n; ++i) cin >> a[i];
		for (int i = 1; i <= m; ++i) {
			int x;
			cin >> x;
			p[x] = true;
		}
		bool flag = false;
		for (int i = 1; i < n; ++i) {
			for (int j = i + 1; j <= n; ++j) {
				if (a[i] > a[j]) {
					int index = i;
					while (index < j && p[index]) ++index;
					if (index < j) {
						flag = true;
						break;
					}
					swap(a[i], a[j]);
				}
			}
			if (flag) break;
		}
		if (flag) cout << "NO" << endl;
		else cout << "YES" << endl;
	}
	return 0;
}

【C.Perform the Combo】

【题目大意】
有一个长度为n的字符串s和一个数组p,你每次打字打到s[pi]时就会从头开始,问你’a’ - 'z’的所有字符被打印的次数是多少

注意最后s还要被完整打印一次

【解题思路】
有一个暴力的O(nm)的做法就是遍历s和p每次将num[s[i]]++,但是显然超时,考虑优化算法,我们可以将s中的字符的位置记录到vector(v[26])中,然后遍历p,如果v[‘a’ - ‘z’]中有字符的位置小于p[i],我们找到其最后一个大于p[i]的位置,复杂度O(m * 26 * lgn)

【AC代码】

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int maxn = 2e5 + 10;
int num[26];
int p[maxn];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		int n, m;
		string s;
		cin >> n >> m >> s;
		memset(num, 0, sizeof(num));
		for (int i = 1; i <= m; ++i) cin >> p[i];
		vector<int> v[26];
		for (int i = 0; i < n; ++i) {
			v[s[i] - 'a'].push_back(i + 1);
			++num[s[i] - 'a'];
		}
		for (int i = 1; i <= m; ++i) {
			for (int j = 0; j < 26; ++j) {
				if (!v[j].size()) continue;
				int index = upper_bound(v[j].begin(), v[j].end(), p[i]) - v[j].begin();
				num[j] += index;
			}
		}
		for (int i = 0; i < 26; ++i) cout << num[i] << " ";
		cout << endl;
	}
	return 0;
}

【D.Three Integers】

【题目大意】
给你三个正整数a,b,c (a <= b <= c),每次你可以将其中一个数加上或减去1,问你最少操作多少次可以使得a整除b且b整除c

【解题思路】
推了半个多小时公式结果最后打了个暴力,没想到正解就是暴力,大概意思就是枚举a和b,首先ansa的范围一定在1到2c之间,然后ansb一定是ansa的倍数,最后考虑将c变成c - c % ansb或者c + ansb - c % ansb,找到所有组合中sum最小的即可

【AC代码】

//当时为了防止超时加了register常数优化
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	register int T;
	cin >> T;
	while (T--) {
		int a, b, c;
		cin >> a >> b >> c;
		register int ansa = a, ansb = b, ansc = c;
		register int sum = 0x3f3f3f3f;
		register int cc = c << 1;
		for (register int i = 1; i <= cc; ++i) {
			for (register int j = i; j <= cc; j += i) {
				int k = 0;
				if (c % j < j - c % j) k = c - c % j;
				else k = c + j - c % j;
				if (sum > abs(i - a) + abs(j - b) + abs(k - c)) {
					sum = abs(i - a) + abs(j - b) + abs(k - c);
					ansa = i, ansb = j, ansc = k;
				}
			}
		}
		cout << sum << endl;
		cout << ansa << " " << ansb << " " << ansc << endl;
	}
	return 0;
}
发布了40 篇原创文章 · 获赞 2 · 访问量 3212

猜你喜欢

转载自blog.csdn.net/weixin_44211980/article/details/104505475