ICPC 2024 武汉邀请赛
I. Cyclic Apple Strings
题目大意
给定一个01字符串,每次可以选择一个子串移动,问至少操作多少次才能最小化字符串字典序
解题思路
统计不在开头的0的段数即可,简单计算就是10子串有多少
代码实现
print(input().count("10"))
K. Party Games
题目大意
f和p在一个升序排列上进行游戏,每次可以删除最左或者最右的数字,当剩余数字异或和为0时获胜,问f先手能否必胜
解题思路
打表找规律
代码实现
for _ in range(int(input())):
n = int(input())
if n // 2 % 2:
print("Pinkie Pie")
else:
print("Fluttershy")
B. Countless Me
题目大意
给定一个数组a,每次操作可以选择\(a_i\)和\(a_j\)变为\(a_i+x\)和\(a_j-x\),一共可以操作n次,最小化数组中所有元素按位与的结果
解题思路
看似只有n次,但是已经可以任意修改所有数字的值,因此只需要每次都从高位加上不小于平均数的二的幂即可
代码实现
import math
n = int(input())
a = sum(list(map(int, input().split())))
ans = 0
while a:
t = 1
while t * 2 <= math.ceil(a / n):
t *= 2
ans += t
a -= min(a // t, n) * t
print(ans)
F. Custom-Made Clothes
题目大意
交互题,用不超过50000次询问找到矩阵第k大的元素,“? i j x”表示询问\(a_{ij}\)是否不大于x,矩阵的每个元素满足都不小于当前位置左边和上面的元素
解题思路
矩阵是一个左上小,右下大的矩阵,为了方便计算,可以转化为求n*n-k+1小的元素,由于矩阵元素有序,因此可以考虑二分目标元素,判断是否有足够数量的数字不小于目标元素
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
int n, k;
std::cin >> n >> k;
k = n * n - k + 1;
auto check = [&](int x) -> bool {
for (int i = 1, cnt = 0, j = n, f; i <= n; i++) {
for (; j > 0; j--) {
std::cout << "? " << i << " " << j << " " << x << std::endl;
std::cin >> f;
if (f) {
break;
}
}
cnt += j;
if (cnt >= k) {
return false;
}
}
return true;
};
int l = 1, r = n * n, ans = 1;
while (l <= r) {
int mid = (l + r) / 2;
if (check(mid)) {
l = mid + 1;
} else {
r = mid - 1;
ans = mid;
}
}
std::cout << "! " << ans << std::endl;
}
D. ICPC
题目大意
给定一个数组,问从每一个位置出发移动1~2n次到达的数字之和的最大值,每次移动可以左移或右移一格
解题思路
显然最优的答案改变方向不会超过一次方向,对两个方向分别计算取大即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int n;
std::cin >> n;
std::vector<i64> pre(n + 1);
for (int i = 1; i <= n; i++) {
int x;
std::cin >> x;
pre[i] = pre[i - 1] + x;
}
std::vector<std::vector<i64>> L(n + 2, std::vector<i64>(n * 2 + 1)), R(n + 2, std::vector<i64>(n * 2 + 1));
for (int i = n; i >= 1; i--) {
for (int j = 1; j <= n * 2; j++) {
L[i][j] = std::max(L[i + 1][j - 1], pre[i] - pre[std::max(1, i - j) - 1]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n * 2; j++) {
R[i][j] = std::max(R[i - 1][j - 1], pre[std::min(n, i + j)] - pre[i - 1]);
}
}
i64 ans = 0;
for (int i = 1; i <= n; i++) {
i64 x = 0;
for (int j = 1; j <= n * 2; j++) {
x ^= (j * std::max(L[i][j], R[i][j]));
}
ans ^= (i + x);
}
std::cout << ans << "\n";
}