前言
F出题人的期望解法是三元环,第一次见,内测时候交出了34发的天文数字,如果有错欢迎大家指出。
题解
A.ACM中的A题
枚举所有情况,分别给每一个木棍乘2试试。
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
void solve() {
std::vector<i64> a;
for (i64 i = 1; i <= 3; i++) {
i64 x;
std::cin >> x;
a.push_back(x);
}
for (int i = 0; i < 3; i++) {
std::vector<i64> v;
for (int j = 0; j < 3; j++) {
if (i == j) {
v.push_back(a[j] * 2);
}
else
v.push_back(a[j]);
}
std::sort (v.begin(), v.end());
if (v[0] + v[1] > v[2]) {
std::cout << "Yes";
return;
}
}
std::cout << "No";
}
signed main() {
std::ios::sync_with_stdio(0);
std::cout.tie(0);
std::cin.tie(0);
i64 t = 1;
// std::cin >> t;
while (t--) {
solve();
}
}
B.ACM中的C题
如果为1无法交换则无解,否则输出除向上取整即可。
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
void solve() {
int n;
std::cin >> n;
for (int i = 1; i <= n; i++) {
int a;
std::cin >> a;
}
if (n == 1) {
std::cout << -1;
}
else {
std::cout << (n + 1) / 2 ;
}
}
signed main() {
std::ios::sync_with_stdio(0);
std::cout.tie(0);
std::cin.tie(0);
i64 t = 1;
// std::cin >> t;
while (t--) {
solve();
}
}
C.ACM中的M题
此题与上一题的区别就是数组可能会属于不同的集合,那把上一题看成数组都属于同一个集合不就好了,本题的答案就是把不同的集合的答案求和,跟上一题一样,如果有某个集合的大小为,那么则无解。
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
void solve() {
int n;
std::cin >> n;
for (int i = 1; i <= n; i++) {
int a;
std::cin >> a;
}
std::map<int, int> mp;
for (int i = 1; i <= n; i++) {
int b;
std::cin >> b;
mp[b]++;
}
std::vector<int> v;
for (auto [x, y] : mp) {
v.push_back(y);
}
int ans = 0;
for (auto it : v) {
ans += (it + 1) / 2;
if (it == 1) {
std::cout << -1;
return;
}
}
std::cout << ans ;
}
signed main() {
std::ios::sync_with_stdio(0);
std::cout.tie(0);
std::cin.tie(0);
i64 t = 1;
// std::cin >> t;
while (t--) {
solve();
}
}
D.ACM中的AC题
我写的史山,先预处理出来每个位置到任意一个传送门的最短距离,所有的传送门连到一个超级源点上,从超级源点开始跑就可以处理出来了,然后就是两个人从一个点开始跑bfs,我的写法是一起扔进去两个点打上编号,代表这个人正着跑,代表这个人跑反方向,然后就是一起跑,如果其中某一个找到终点了,就算看一下另一个点的位置到任意传送门的最短路,每次把目前走的距离加上另一个点还需要走的距离取个最小值即可。
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
int dx1[4] = {0, 1, 0, -1};
int dy1[4] = {1, 0, -1, 0};
int dx2[4] = {0, -1, 0, 1};
int dy2[4] = {-1, 0, 1, 0};
void solve() {
int n, m, a, b;
std::cin >> n >> m >> a >> b;
std::vector<std::vector<char> > mp(n + 1, std::vector<char> (m + 1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
std::cin >> mp[i][j];
}
}
std::queue<std::tuple<int, int> > st;
std::vector<std::vector<int > > dist(n + 1, std::vector<int> (m + 1, -1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
std::cin >> mp[i][j];
if (mp[i][j] == '@') {
st.push({i, j});
dist[i][j] = 0;
}
}
}
while (!st.empty()) {
auto [x, y] = st.front();
st.pop();
for (int i = 0; i < 4; i++) {
int xx = x + dx1[i], yy = y + dy1[i];
if (xx < 1 || xx > n || yy < 1 || yy > m || mp[xx][yy] == '#' || dist[xx][yy] != -1) continue;
dist[xx][yy] = dist[x][y] + 1;
st.push({xx, yy});
}
}
std::queue<std::tuple<int, int, int> > q;
std::vector<std::vector<std::vector<int> > > vis(n + 1, std::vector<std::vector<int> > (m + 1, std::vector<int> (2, -1)));
q.push({a, b, 0});//0表示正常走
q.push({a, b, 1});//1表示反着走
vis[a][b][0] = 0;
vis[a][b][1] = 0;
int ans = 1e9;
int sx = -1, sy = -1, flag = 1;
while (!q.empty()) {
auto [x1, y1, op1] = q.front();
q.pop();
auto [x2, y2, op2] = q.front();
q.pop();
if (mp[x1][y1] == '@') {
ans = std::min(ans, vis[x1][y1][0] + dist[x2][y2]);
flag = 0;
}
if (mp[x2][y2] == '@') {
ans = std::min(ans, vis[x2][y2][1] + dist[x1][y1]);
flag = 0;
}
for (int i = 0; i < 4; i++) {
int xx1 = x1 + dx1[i], yy1 = y1 + dy1[i];
if (xx1 < 1 || xx1 > n || yy1 < 1 || yy1 > m || mp[xx1][yy1] == '#' || vis[xx1][yy1][op1] != -1) continue;
int xx2 = x2 + dx2[i], yy2 = y2 + dy2[i];
if (xx2 < 1 || xx2 > n || yy2 < 1 || yy2 > m || mp[xx2][yy2] == '#' || vis[xx2][yy2][op2] != -1) continue;
vis[xx1][yy1][op1] = vis[x1][y1][op1] + 1;
vis[xx2][yy2][op2] = vis[x2][y2][op2] + 1;
q.push({xx1, yy1, op1});
q.push({xx2, yy2, op2});
}
}
if (flag) {
std::cout << -1;
return;
}
std::cout << ans;
}
signed main() {
std::ios::sync_with_stdio(0);
std::cout.tie(0);
std::cin.tie(0);
i64 t = 1;
// std::cin >> t;
while (t--) {
solve();
}
}
E.ACM中的CM题
忽略我代码里的层循环,是我内测时候无聊就想试试最少多少层循环可以AC本题,并没有什么实际意义,直接跑n层就可以,思路也很简单,排序之后就枚举排雷能力是多少,每次就排着段区间内的雷,一直往后跳,看需要跳多少次,这个复杂度是调和级数可以做到,所以整体来说就是。
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
std::vector<int> a;
int n, k;
int check(int x) {
int ans = x;
int pos = a[1];
while (1) {
ans++;
pos = std::upper_bound(a.begin() + 1, a.end(), pos + x) - a.begin();
if (pos == a.end() - a.begin()) break;
pos = a[pos];
}
return ans;
}
void solve() {
std::cin >> n;
a.push_back(0);
for (int i = 1; i <= n; i++) {
int v;
std::cin >> v;
a.push_back(v);
}
std::sort(a.begin() + 1, a.end());
int ans = 1e6;
for (int i = 0; i <= 553; i++) {
ans = std::min(ans, check(i));
}
std::cout << ans << '\n';
}
signed main() {
std::ios::sync_with_stdio(0);
std::cout.tie(0);
std::cin.tie(0);
i64 t = 1;
// std::cin >> t;
while (t--) {
solve();
}
}
F.ACM中的ACM题
三元环的模板题,在本题之前我并未见过,所以卡死了,把判出来三元环的三条边并查集合并即可,最终看看有多少个条边的祖宗是自己,如果只有一个就是否则
#include<bits/stdc++.h>
#include <bits/extc++.h>
using i64 = long long;
using u64 = unsigned long long;
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<int> p(m + 1);
auto find = [&] (auto self, int &x) -> int {
if (x == p[x]) return x;
return p[x] = self(self, p[x]);
};
auto merge = [&] (int &a, int &b) -> void {
int fa = find(find, a), fb = find(find, b);
if (fa != fb) {
p[fb] = fa;
}
};
std::vector<int> in(n + 1), u(m + 1), v(m + 1);
for (int i = 1; i <= m; i++) {
std::cin >> u[i] >> v[i];
in[u[i]]++,in[v[i]]++;
p[i] = i;
}
std::vector<std::vector<std::pair<int,int>> > e(n + 1);
for (int i = 1; i <= m; i++) {
if (in[u[i]] < in[v[i]] || (in[u[i]] == in[v[i]] && u[i] < v[i])) {
e[v[i]].push_back({u[i],i});
}
else {
e[u[i]].push_back({v[i],i});
}
}
std::vector<std::pair<int,int> > vis(n + 1);
for (int i = 1; i <= n; i++) {
for (auto [x, j] : e[i]) vis[x] = {i, j};
for (auto [x,j] : e[i]) {
for (auto [y,k] : e[x]) {
if (vis[y].first == i) {
merge(k, j);
merge(j, vis[y].second );
}
}
}
}
int ans=0;
for (int i = 1; i <= m; i++) {
if(p[i]==i) ans++;
}
if(ans==1)std::cout<<"Yes\n";
else std::cout<<"No\n";
}
signed main() {
std::ios::sync_with_stdio(0);
std::cout.tie(0);
std::cin.tie(0);
i64 t = 1;
std::cin >> t;
while (t--) {
solve();
}
}