Codeforces Global Round 7 解题报告

Codeforces Global Round 7

【A.Bad Ugly Numbers】

【题目大意】
让你找一个由n个数字组成且不能被任意位上的数字整除并且不包含0的数字

【解题思路】
考虑n个数字只有2和3,那么只要构造一个不能被2和3整除的数就好了

【AC代码】

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int maxn = 1e6 + 10;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		int n;
		cin >> n;
		if (n == 1) {
			cout << -1 << endl;
		}
		else {
			int nn = (n - 1) % 3 == 0 ? n - 2 : n - 1;
			for (int i = 1; i <= nn; ++i) cout << 2;
			for (int i = nn + 1; i <= n; ++i) cout << 3;
			cout << endl;
		}
	}
	return 0;
}

【B.Maximums】

【题目大意】
x[i] = max(0, a[1], … , a[i - 1])
b[i] = a[i] - x[i]
给你b数组让你重新构造满足条件的a数组

【解题思路】
b[i] = a[i] - x[i] = a[i] - max(0, a[1], … , a[i - 1])
a[i] = b[i] + max(0, a[1], … , a[i - 1])
那么a[1] = b[1]是显然的
a[2] = b[2] + max(0, a[1])
a[3] = b[3] + max(0, a[1], a[2])

令Max = max(0, a[1], … , a[i - 1])
a[i] = b[i] + Max
容易发现满足递推关系

【AC代码】

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int maxn = 1e6 + 10;
ll a[maxn], b[maxn];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> b[i];
	a[1] = b[1];
	ll Max = a[1];
	for (int i = 2; i <= n; ++i) {
		a[i] = Max + b[i];
		Max = max(Max, a[i]);
	}
	for (int i = 1; i <= n; ++i) cout << a[i] << " ";
	return 0;
}

【D1.Prefix-Suffix Palindrome (Easy version)】

【题目大意】
给你一个字符串s,让你找到它的一个子串t,满足:

  1. t是回文串
  2. t = a + b,其中a为s一个前缀,b为s一个后缀(可以为空)

【解题思路】
这是Easy版本,考虑暴力枚举,首先O(n),找到一个回文的前后缀,然后找到由当前下标开始的最长回文子串
比如说abcdfdcecba
先找到前缀abc和后缀cba,然后找到dfd和e,发现len(dfd) > len(e),那么t = abcdfdcba

【AC代码】

#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--) {
		register string s;
		cin >> s;
		register int l = s.length();
		register string p, pp;
		register int left = 0, right = l - 1;
		while (true) {
			if (s[left] == s[right]) {
				p += s[left];
				pp += s[right];
			}
			else break;
			++left, --right;
			if (left >= right) break;
		}
		if (left >= right) cout << s << endl;
		else {
			register string ll, rr;
			for (int i = right - left + 1; i >= 1; --i) {
				register string t = s.substr(left, i);
				register string tt = t;
				reverse(t.begin(), t.end());
				if (t == tt) {
					ll = t;
					break;
				}
			}
			for (int i = right - left + 1; i >= 1; --i) {
				register string t = s.substr(right - i + 1, i);
				register string tt = t;
				reverse(t.begin(), t.end());
				if (t == tt) {
					rr = t;
					break;
				}
			}
			cout << p;
			if (ll.length() > rr.length()) cout << ll;
			else cout << rr;
			reverse(pp.begin(), pp.end());
			cout << pp << endl;
		}
	}
	return 0;
}

【D2.Prefix-Suffix Palindrome (Hard version)】

【题目大意】
和D1相同,只是s的length变成了1e6

【解题思路】
D1中找回文串的方法是O(n2),显然会超时,这时我们需要O(n)的马拉车算法来帮助我们找到最长回文

扫描二维码关注公众号,回复: 10935302 查看本文章

千万不要用string中的s = p + s,会超时

【AC代码】

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int maxn = 2e6 + 10;
int p[maxn];
char t[maxn];
inline void Manacher(register string s) {
	register int lt = 0;
	register int ls = s.length();
	t[++lt] = '$';
	t[++lt] = '#';
	for (register int i = 0; i < ls; ++i) {
		t[++lt] = s[i];
		t[++lt] = '#';
	}
	t[++lt] = '\0';
	register int mx = 0, id = 0, reCenter = 0, reLen = 0;
	for (register int i = 2; i < lt; ++i) {
		p[i] = mx > i ? min(mx - i, p[2 * id - i]) : 1;
		while (t[i + p[i]] == t[i - p[i]]) ++p[i];
		if (i + p[i] > mx) {
			mx = i + p[i];
			id = i;
		}
		if ((i - p[i] <= 1 || i + p[i] >= lt) && p[i] > reLen) {
			reLen = p[i];
			reCenter = i;
		}
	}
	memset(p, 0, lt * sizeof(int));
	cout << s.substr((reCenter - reLen) / 2, reLen - 1);
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	register int T;
	cin >> T;
	while (T--) {
		register string s;
		cin >> s;
		register int l = s.length();
		register string p, pp;
		register int left = 0, right = l - 1;
		while (true) {
			if (s[left] == s[right]) {
				p += s[left];
				pp += s[right];
			}
			else break;
			++left, --right;
			if (left >= right) break;
		}
		if (left >= right) cout << s << endl;
		else {
			cout << p;
			Manacher(s.substr(left, right - left + 1));
			reverse(pp.begin(), pp.end());
			cout << pp << endl;
		}
	}
	return 0;
}
发布了40 篇原创文章 · 获赞 2 · 访问量 3209

猜你喜欢

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