比赛链接
A. Qfish的魔方
Solution
把输入的 9 9 9 个数排序,然后 3 3 3 个 3 3 3 个地逐行放进一共 3 × 3 3 \times 3 3×3 的二维数组里,最后根据题意判断即可。
C++ Code
#include <bits/stdc++.h>
using i64 = int64_t;
using u64 = uint64_t;
using f64 = double_t;
using i128 = __int128_t;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout << std::fixed << std::setprecision(12);
std::array<int, 9> a{
};
for (int i = 0; i < 9; i++) {
std::cin >> a[i];
}
std::ranges::sort(a);
std::array<std::array<int, 3>, 3> g{
};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
g[i][j] = a[i * 3 + j];
}
}
for (int i = 0; i < 3; i++) {
if (std::count(g[i].begin(), g[i].end(), g[i][0]) != 3) {
std::cout << "No\n";
return 0;
}
if (i + 1 < 3) {
for (int j = 0; j < 3; j++) {
if (g[i + 1][j] <= g[i][j]) {
std::cout << "No\n";
return 0;
}
}
}
}
std::cout << "Yes\n";
return 0;
}
B. 寻找最大值
Solutioin
按照题意模拟交换字符即可。
C++ Code
#include <bits/stdc++.h>
using i64 = int64_t;
using u64 = uint64_t;
using f64 = double_t;
using i128 = __int128_t;
void solve() {
int N;
std::cin >> N;
std::string S;
std::cin >> S;
i64 ans = std::stoll(S);
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
std::swap(S[i], S[j]);
ans = std::max<i64>(ans, std::stoll(S));
std::swap(S[i], S[j]);
}
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout << std::fixed << std::setprecision(12);
int T = 1;
std::cin >> T;
while (T--) {
solve();
}
return 0;
}
C. 找数字
Solution
同样是按照题意模拟,记录每个数的出现次数。
C++ Code
#include <bits/stdc++.h>
using i64 = int64_t;
using u64 = uint64_t;
using f64 = double_t;
using i128 = __int128_t;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout << std::fixed << std::setprecision(12);
int n;
std::cin >> n;
std::map<int, int> cnt;
for (int i = 0; i < n; i++) {
int x;
std::cin >> x;
cnt[x]++;
}
int tot = 0;
for (const auto &[k, v]: cnt) {
if (v == 1) {
std::cout << k << " \n"[++tot == 2];
}
}
return 0;
}
D. 找更多的数字
题目大意
给定一个长度为 n n n 的数组 a a a,现在有 q q q 次询问。
每次询问,给定 l , r l, \ r l, r,对于子数组 a [ l . . . r ] a[l...r] a[l...r],保证其中有 2 2 2 个只出现 1 1 1 次的数字,其他数字都出现了 2 2 2 次。
请你找到这 2 2 2 个只出现 1 1 1 次的数,从小到大输出。
数据范围
- 1 ⩽ n ⩽ 1 0 5 1 \leqslant n \leqslant 10^5 1⩽n⩽105;
- 0 ⩽ a i ⩽ 1 0 6 0 \leqslant a_i \leqslant 10^6 0⩽ai⩽106;
- 1 ⩽ q ⩽ 1 0 6 1 \leqslant q \leqslant 10^6 1⩽q⩽106;
- 1 ⩽ l < r ⩽ n 1 \leqslant l < r \leqslant n 1⩽l<r⩽n,且保证 [ l , r ] [l, \ r] [l, r] 内满足仅有 2 2 2 个数出现 1 1 1 次,其余均出现 2 2 2 次。
Solution
不妨设那 2 2 2 个特殊的数是 x , y x, \ y x, y。
由题意可得,对于给定区间 [ l , r ] [l, \ r] [l, r] 的前缀异或和,得到的结果一定是 x ⊕ y x \oplus y x⊕y( x , y x, \ y x, y 都是只出现一次)。
考虑用 x ⊕ y x \oplus y x⊕y 的某一位为 1 1 1 的二进制位,来找到 x x x 或者 y y y。不妨设这一位是第 k k k 位。
对于前缀异或和,可以考虑其变种:
拆位前缀异或和,即对每一位都开一个前缀和数组,且仅考虑每一位为 1 的时候将数异或上去。
这样的话对于给定区间 [ l , r ] [l, \ r] [l, r],由于限制了其余数均出现 2 2 2 次,所以不论第 k k k 位上其余数是什么,整段区间(除了 x , y x, \ y x, y)在这一位上的前缀异或和都是 0 0 0,又因为 x x x 和 y y y 只有一个数在第 k k k 位是 1 1 1(它们的异或值 x ⊕ y x \oplus y x⊕y 在第 k k k 位是 1 1 1,所以最后会得到 x x x 或者 y y y。
时间复杂度 O ( 20 n ) \mathcal{O}(20n) O(20n)
C++ Code
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, q;
std::cin >> n >> q;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::vector<int> s(n + 1);
std::vector<std::array<int, 20>> xs(n + 1);
for (int i = 0; i < n; i++) {
s[i + 1] = s[i] ^ a[i];
for (int j = 0; j < 20; j++) {
xs[i + 1][j] = xs[i][j] ^ ((a[i] >> j & 1) * a[i]);
}
}
while (q--) {
int l, r;
std::cin >> l >> r;
l--;
int v = s[r] ^ s[l];
for (int i = 0; i < 20; i++) {
if (v >> i & 1) {
int x = xs[r][i] ^ xs[l][i];
int y = x ^ v;
if (x > y) {
std::swap(x, y);
}
std::cout << x << " " << y << "\n";
break;
}
}
}
return 0;
}
E. 井字棋
Solution
同样是按题意模拟,判断每列、每行、对角线、反对角线
C++ Code
#include <bits/stdc++.h>
using i64 = int64_t;
using u64 = uint64_t;
using f64 = double_t;
using i128 = __int128_t;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout << std::fixed << std::setprecision(12);
std::array<std::string, 3> g{
};
for (int i = 0; i < 3; i++) {
std::cin >> g[i];
}
auto check = [&](char c) {
if (g[0][0] == c and g[0][0] == g[1