Codeforces Round 1007 (Div. 2)
A. The Play Never Ends
题目大意
ABC三人比赛,谁输谁下场,任何一人2连胜都要下场,问第1次比赛的观众能不能是第k次比赛的观众
解题思路
简单打表即可发现答案为 k%3==1 的时候是
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int x;
std::cin >> x;
if (x % 3 == 1) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
}
}
B. Perfecto
题目大意
构造一个排列,要求他的前缀和不能有完全平方数,不能构造输出-1
解题思路
如果总和是完全平方数,最后一个一定会是,因此输出-1,否则遍历过去算前缀和即可,如果当前是,则当前+1一定不是(没有差值为1的正完全平方数)
代码实现
#include <bits/stdc++.h>
using i64 = long long;
bool check(i64 n) {
i64 x = std::sqrt(n);
return x * x == n;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
i64 n;
std::cin >> n;
i64 sum = n * (n + 1) / 2;
if (check(sum)) {
std::cout << -1 << "\n";
continue;
}
std::vector<int> p(n);
std::iota(p.begin(), p.end(), 1);
for (i64 i = 1; i < n; i++) {
if (check(i * (i + 1) / 2)) {
std::swap(p[i], p[i - 1]);
}
}
for (auto x : p) {
std::cout << x << " \n"[x == p.back()];
}
}
}
C. Trapmigiano Reggiano
题目大意
给你一棵树,构造一个排列,从起点开始,按照排列走,要求最后停留在终点,一次只能走一步,如果不能一步走到,则朝目标节点方向走一步,无法构造输出-1
解题思路
首先可以知道的是一定可以构造,因为最后要回到ed,所以其实并不在意哪里是st,以ed为树的根跑一遍bfs可以让前面的操作全都相互抵消,最后翻转输出即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, st, ed;
std::cin >> n >> st >> ed;
std::vector<int> vis(n + 1), ans;
std::vector<std::vector<int>> g(n + 1, std::vector<int>());
for (int i = 1; i <= n - 1; i++) {
int u, v;
std::cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
std::queue<int> q;
q.push(ed);
vis[ed] = 1;
ans.push_back(ed);
while (!q.empty()) {
int u = q.front();
q.pop();
for (auto v : g[u]) {
if (!vis[v]) {
vis[v] = 1;
q.push(v);
ans.push_back(v);
}
}
}
std::reverse(ans.begin(), ans.end());
for (auto x : ans) {
std::cout << x << " \n"[x == ans.back()];
}
}
}
D1. Infinite Sequence (Easy Version)
题目大意
给你一个无限长的01串前n项,对于大于n的位置m,由前 \(m/2\)(下取整) 的前缀异或和得到,问lr区间的和是多少,对于简单版本,l==r
解题思路
对于m>n的位置,如果m是偶数,那么 \(a[m]=a[m+1]\) , \([n,m/2]\) 区间里的成对的奇偶数异或之后被抵消掉了,所以只需要判断 \(m/2\) 是不是偶数位置
设 \([1,n]\) 的前缀异或和为pre
- 如果 \(m/2\) 是奇数,那么可以和前面的偶数位置抵消,\(a[m]=pre\)
- 如果 \(m/2\) 是偶数,那么 \(a[m]=pre \bigoplus a[m/2]\),之后就可以递归地求 \(a[m/2]\),如果小于等于n了就可以直接返回结果
此外需要判断n的奇偶性,当n为偶数的时候,需要修正递归途中的最后一次n/2
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
i64 n, l, r;
std::cin >> n >> l >> r;
std::vector<i64> a(n), pre(n + 1);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
pre[i + 1] = pre[i] ^ a[i];
}
if (l <= n) {
std::cout << a[l - 1] << "\n";
} else {
i64 X = pre[n];
if (n % 2 == 0) {
X ^= pre[n / 2];
}
auto dfs = [&](auto &&self, i64 x) -> i64 {
if (x <= n) {
return pre[x];
}
if (x % 2) {
return X;
}
return X ^ self(self, x / 2);
};
std::cout << dfs(dfs, l / 2) << "\n";
}
}
}

浙公网安备 33010602011771号