Codeforces Round #713 (Div. 3)
昨天下午监考招新赛时做的 =。= 话说前天晚上验题时还想着这么简单肯定会有人 ak 来着,结果第一过题数也才 9/12 。
比赛链接:https://codeforces.com/contest/1512
A. Spy Detected!
题解一
记录每个值所在的下标,之后遍历一遍找到只有一个下标的值。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<vector<int>> pos(105);
for (int i = 0; i < n; i++) {
int x;
cin >> x;
pos[x].push_back(i);
}
for (auto vec : pos) {
if (vec.size() == 1) {
cout << vec.back() + 1 << "\n";
}
}
}
return 0;
}
题解二
因为数组中只有两个值,不论只出现了一次的值是大是小,排序后一定是在首尾之一,所以排序后在数组中第二个位置的值一定为多次出现的值。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<int> b(a);
sort(b.begin(), b.end());
for (int i = 0; i < n; i++) {
if (a[i] != b[1]) {
cout << i << "\n";
}
}
}
return 0;
}
B. Almost Rectangle
题解
记录 * 所在的横纵坐标,之后 \(2 \times 2\) 组合即可。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<string> MP(n);
set<int> x, y;
for (int i = 0; i < n; i++) {
cin >> MP[i];
for (int j = 0; j < n; j++) {
if (MP[i][j] == '*') {
x.insert(i);
y.insert(j);
}
}
}
auto to_two = [&](set<int>& st) {
if (st.size() == 1) {
if (*st.begin() + 1 < n) {
st.insert(*st.begin() + 1);
} else {
st.insert(*st.begin() - 1);
}
}
};
to_two(x), to_two(y);
for (auto i : x) {
for (auto j : y) {
MP[i][j] = '*';
}
}
for (int i = 0; i < n; i++) {
cout << MP[i] << "\n";
}
}
return 0;
}
C. A-B Palindrome
题解
先处理字符串中必须替换的字符,即一方为 ? 一方为 0 或 1 的情况,之后将成对的 ? 替换即可。
Tips
成对替换时如果是奇回文串的中心部分只要一个 0 或 1 就可以了。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int a, b;
cin >> a >> b;
string s;
cin >> s;
int n = a + b;
a -= count(s.begin(), s.end(), '0');
b -= count(s.begin(), s.end(), '1');
for (int i = 0; i < n; i++) {
if (s[i] != '?' and s[n - 1 - i] == '?') {
if (s[i] == '0' and a > 0) {
s[n - 1 - i] = s[i];
--a;
} else if (s[i] == '1' and b > 0) {
s[n - 1 - i] = s[i];
--b;
}
}
}
for (int i = 0; i < n; i++) {
if (s[i] == '?' and s[n - 1 - i] == '?') {
int sub = 1 + (i != n - 1 - i);
if (a >= sub) {
s[i] = s[n - 1 - i] = '0';
a -= sub;
} else if (b >= sub) {
s[i] = s[n - 1 - i] = '1';
b -= sub;
}
}
}
if (max(a, b) == 0 and s == string(s.rbegin(), s.rend())) {
cout << s << "\n";
} else {
cout << -1 << "\n";
}
}
return 0;
}
D. Corrupted Array
题解
\(\sum_{i = 1}^{n + 2} \limits b_i = 2b_{n + 1} + x\) ,枚举 \(x\) ,判断 \(b\) 中是否存在相应的 \(b_{n + 1}\) ,如果存在,去除 \(x\) 和 \(b_{n + 1}\) 即可。
Tips
本题官方题解有一点与题目矛盾,就是必须加上 \(2b_{n+1} = (\sum_{i = 1}^{n + 2} \limits b_i) - x \le 2 \times 10^9\) 的判断条件,因为按照题目输入中的限制, \(b_i \le 10^9\) ,所以即使 \((\sum_{i = 1}^{n + 2} \limits b_i) - x > 2 \times 10^9\) ,也不会存在相应大小的 \(b_{n + 1}\) 。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> b(n + 2);
long long sum = 0;
for (int i = 0; i < n + 2; i++) {
cin >> b[i];
sum += b[i];
}
multiset<int> mst(b.begin(), b.end());
for (int i = 0; i < n + 2; i++) {
int x = b[i];
if ((sum - x) <= 2'000'000'000 and (sum - x) % 2 == 0 and (x == (sum - x) / 2 ? mst.count(x) >= 2 : mst.count((sum - x) / 2))) {
mst.erase(mst.find(x));
mst.erase(mst.find((sum - x) / 2));
for (auto val : mst) {
cout << val << ' ';
}
cout << "\n";
break;
} else if (i == n + 1) {
cout << -1 << "\n";
}
}
}
return 0;
}
E. Permutation by Sum
题解
先以 \(1,\ 2\ ...\ \ r - l + 1\) 填充 \(p_l,\ p_{l+1}\ ...\ p_r\) ,之后为每个数加上 \(\lfloor \frac{s - \sum_{i = l}^{r} \limits p_i}{len} \rfloor\) ,如果还有余数,因为区间中的数是连续的,所以需要从右端点往左加。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n, l, r, s;
cin >> n >> l >> r >> s;
--l, --r;
int seg_len = r - l + 1;
vector<int> p(seg_len);
iota(p.begin(), p.end(), 1);
int sum = (1 + seg_len) * seg_len / 2;
int extra_need = max(0, s - sum) / seg_len;
for (int i = 0; i < seg_len; i++) {
p[i] += extra_need;
}
for (int i = 0; i < (s - sum - extra_need * seg_len); i++) {
++p[seg_len - 1 - i];
}
if (sum > s or p.back() > n) {
cout << -1 << "\n";
} else {
set<int> st;
for (int i = 1; i <= n; i++) {
st.insert(i);
}
vector<int> ans(n);
for (int i = l; i <= r; i++) {
ans[i] = p[i - l];
st.erase(ans[i]);
}
for (int i = 0; i < n; i++) {
if (ans[i] == 0) {
ans[i] = *st.begin();
st.erase(st.begin());
}
}
for (int i = 0; i < n; i++) {
cout << ans[i] << " \n"[i == n - 1];
}
}
}
return 0;
}
F. Education
题解
枚举以每个职位为终点挣够 \(c\) 所需的天数即可。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
#define int long long
int t;
cin >> t;
while (t--) {
int n, c;
cin >> n >> c;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<int> b(n - 1);
for (int i = 0; i < n - 1; i++) {
cin >> b[i];
}
int ans = INT_MAX;
int now = 0, days = 0;
for (int i = 0; i < n; i++) {
if (now >= c) {
ans = min(ans, days);
} else {
ans = min(ans, days + (c - now + a[i] - 1) / a[i]);
}
if (i < n - 1) {
if (now >= b[i]) {
now -= b[i];
++days;
} else {
int day = (b[i] - now + a[i] - 1) / a[i];
now += day * a[i] - b[i];
days += day + 1;
}
}
}
cout << ans << "\n";
}
return 0;
}
G. Short Task
题解
埃筛一遍即可。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
const int N = 1e7 + 10;
vector<int> d(N), ans(N, -1);
for (int i = 1; i < N; i++) {
for (int j = i; j < N; j += i) {
d[j] += i;
}
}
for (int i = 1; i < N; i++) {
if (d[i] < N and ans[d[i]] == -1) {
ans[d[i]] = i;
}
}
int t;
cin >> t;
while (t--) {
int c;
cin >> c;
cout << ans[c] << "\n";
}
return 0;
}