AtCoder Beginner Contest 413
比赛链接如下:Denso Create Programming Contest 2025(AtCoder Beginner Contest 413) - AtCoder
A - Content Too Large
Problem Statement
Takahashi has N items and one bag.The size of the i-th (1≤i≤N) item is Ai, and the size of the bag is M.
If and only if the total size of the items he is trying to put in the bag is at most M, he can put all those items in the bag simultaneously.
If he can put all N items in the bag simultaneously, print Yes; otherwise, print No.
解题思路:
一次性将N件物品装入大小为M的包中, 能装进去, 输出Yes, 否则, 输出No
#include <bits/stdc++.h>
using namespace std;
void solve() {int n,m;cin>>n>>m;vector<int> a(n);int sum_a=0;for(int i=0;i<n;i++){cin>>a[i];sum_a+=a[i];}if(sum_a<=m){cout<<"Yes"<<'\n';}else{cout<<"No"<<'\n';}
}
int main() {int t=1;// cin >> t;while (t--) {solve();}return 0;
}
B - cat 2
Problem Statement
You are given N types of strings S1,S2,…,SN.You perform the following operation once:
Choose distinct integers i and j (1≤i≤N,1≤j≤N) and concatenate Si and Sj in this order.
How many different strings can be obtained as a result of this operation?If different choices of (i,j) result in the same concatenated string, it is counted as one string.
解题思路:
将两个下标不同的字符串进行合并, 然后存入到一个set中, 输出set的长度即可
#include <bits/stdc++.h>
using namespace std;
void solve() {int n;cin >> n;vector<string> a(n);for (int i = 0; i < n; i++) {cin >> a[i];}set<string> st;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (i == j)continue;st.insert(a[i] + a[j]);}}cout << st.size() << '\n';
}
int main() {int t = 1;// cin >> t;while (t--) {solve();}return 0;
}
C - Large Queue
Problem Statement
There is an empty integer sequence A=(). You are given Q queries, and you need to process them in the given order. There are two types of queries:Type 1: Given in the format 1 c x. Add c copies of x to the end of A.
Type 2: Given in the format 2 k. Remove the first k elements from A and output the sum of the removed k integers. It is guaranteed that k is at most the length of A at that time.
解题思路:
两种操作, 一种是在A的尾部添加c个x, 另一种是移除A的前k个元素, k的值不能超过A的长度, 同时输出这个k个元素的总和,使用deque维护这个数组A, 然后t=1/2进行操作即可
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
void solve() {int q;cin >> q;deque<pll> dp;while (q--) {int t;cin >> t;if (t == 1) {ll c, x;cin >> c >> x;dp.emplace_back(c, x);} else {ll k;cin >> k;ll sum = 0;while (k > 0 && !dp.empty()) {auto& a = dp.front();ll c = a.first; ll x = a.second; if (c <= k) {sum += c * x;k -= c;dp.pop_front();} else {sum += k * x;a.first -= k;k = 0;}}cout << sum << "\n";}}
}
int main() {int t=1;// cin>>t;while(t--){solve();}return 0;
}
D - Make Geometric Sequence
Problem Statement
You are given an integer sequence A=(A1,A2,…,AN) of length N. It is guaranteed that for any i (1≤i≤N), Ai is not 0.Determine whether there exists a permutation B=(B1,B2,…,BN) of A such that B forms a geometric sequence.
A sequence S=(S1,S2,…,SN) is a geometric sequence if there exists a real number r such that Si+1=rSi for all integers 1≤i<N.
Solve T test cases per input file.
解题思路:
判断数组A的某个排列能否构成等比数列
1. 数组长度<=2的数列是等比数列
2. 数组元素相等, 公比q=1
3. 公比q正负交替的情况(互为相反数)
=> 只有两个值,且互为相反数,数量差不大于1
4. 一般情况通过 b[i]^2 = b[i-1]*b[i+1]进行判断
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
void solve() {int n;cin >> n;vector<ll> a(n);for (int i = 0; i < n; i++) {cin >> a[i];}if (n <= 2) {cout << "Yes" << '\n';return;}bool f = true;for (int i = 1; i < n; i++) {if (a[i] != a[0]) {f = false;break;}}if (f) {cout << "Yes" << '\n';return;}set<ll> v(a.begin(), a.end());if (v.size() == 2) {auto it = v.begin();ll v1 = *it;it++;ll v2 = *it;if (v1 + v2 == 0) {ll c1 = 0, c2 = 0;for (ll x : a) {if (x == v1)c1++;elsec2++;}if (abs(c1 - c2) <= 1) {cout << "Yes" << '\n';return;}}}sort(a.begin(), a.end(), [](ll x, ll y) { return llabs(x) < llabs(y); });bool f_1 = true;for (int i = 1; i + 1 < n; i++) {ll x = (ll)a[i] * a[i];ll y = (ll)a[i - 1] * a[i + 1];if (x != y) {f_1 = false;break;}}if (f_1)cout << "Yes" << '\n';elsecout << "No" << '\n';
}
int main() {int t;cin >> t;while (t--) {solve();}return 0;
}
E - Reverse 2^i
Problem Statement
You are given a permutation P=(P0,P1,…,P2N−1) of (1,2,3,…,2N).You can perform the following operation any number of times (possibly zero):
Choose non-negative integers a,b satisfying 0≤a×2b<(a+1)×2b≤2N, and reverse Pa×2b,Pa×2b+1,…,P(a+1)×2b−1. Here, reversing Pa×2b,Pa×2b+1,…,P(a+1)×2b−1 means simultaneously replacing Pa×2b,Pa×2b+1,…,P(a+1)×2b−1 with P(a+1)×2b−1,P(a+1)×2b−2,…,Pa×2b.
Find the lexicographically smallest permutation P that can be obtained by repeating the operation.You are given T test cases, so find the answer for each.
解题思路:
你有一个长度为 2^n 的排列 P,你可以对它做若干次以下操作:
选择两个整数 a,b,满足区间 [a⋅2^b,(a+1)⋅2^b−1] 在数组范围内,把这个区间反转。
你要找到经过若干次这种操作后,能得到的字典序最小的排列。
观察可得:
每次反转的区间长度必须是 2^b,并且是从 a⋅2^b 开始(即按块划分)。
实际上这与 对二叉划分结构的左右子树进行翻转是等价的。
在二叉树的每一级都尝试“原顺序”或“左右块交换”,递归比较返回最小结果
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
vector<ll> dfs(vector<ll>& a, int i, int j) {if (j == 0) {return {a[i]};}auto x = dfs(a, i, j - 1);auto y = dfs(a, i + (1 << (j - 1)), j - 1);vector<ll> m;m.insert(m.end(), x.begin(), x.end());m.insert(m.end(), y.begin(), y.end());vector<ll> t;t.insert(t.end(), y.begin(), y.end());t.insert(t.end(), x.begin(), x.end());if (m <= t) {return m;} else {return t;}
}
void solve() {int n;cin >> n;vector<ll> a(1 << n);for (int i = 0; i < (1 << n); i++) {cin >> a[i];}vector<ll> ans = dfs(a, 0, n);for (int i = 0; i < (1 << n); i++) {cout << ans[i];if (i < ans.size() - 1)cout << ' ';elsecout << '\n';}
}
int main() {int t;cin >> t;while (t--) {solve();}return 0;
}
F - No Passag
Probl
em Statement
There is an H×W grid. Let (i,j) denote the cell at the i-th row from the top and j-th column from the left. Among these, K cells are goals. The i-th goal (1≤i≤K) is cell (Ri,Ci).Takahashi and Aoki play a game using this grid and a single piece placed on the grid. Takahashi and Aoki repeatedly perform the following series of operations until the piece reaches a goal cell:
Aoki chooses an integer a between 1 and 4, inclusive.
Then, Takahashi chooses an integer b between 1 and 4, inclusive, where a=b must be satisfied. Let (i,j) be the cell where the piece is placed before the operation. Based on the chosen integer b and the piece's position, move the piece.
When b=1: If (i−1,j) is within the grid, move the piece from cell (i,j) to cell (i−1,j); if it is outside the grid, do nothing.
When b=2: If (i+1,j) is within the grid, move the piece from cell (i,j) to cell (i+1,j); if it is outside the grid, do nothing.
When b=3: If (i,j−1) is within the grid, move the piece from cell (i,j) to cell (i,j−1); if it is outside the grid, do nothing.
When b=4: If (i,j+1) is within the grid, move the piece from cell (i,j) to cell (i,j+1); if it is outside the grid, do nothing.
Takahashi's objective is to minimize the number of moves until the piece reaches a goal. Aoki's objective is to prevent the piece from reaching the goal; if that is impossible, his objective is to maximize the number of moves until the piece reaches a goal.For all pairs of integers (i,j) satisfying 1≤i≤H,1≤j≤W, solve the following problem and find the sum of all solutions:
Start the game with the piece at cell (i,j). Assume both players act optimally toward their respective objectives. If Takahashi can make the piece reach a goal, the solution is the minimum number of moves; otherwise, the solution is 0.
解题思路:
1.dp[i] 表示从 i 出发走到目标所需最小步数
2.用 Dijkstra 从目标反向扩展
3. Aoki 选 1~4 中一项,Takahashi 从剩下中选最优方向。确保最坏情况最优
4. 对于每个点,找出在任意 Aoki 决策下,Takahashi 的最小可行步数,再加一更新
5. 最后, 累加所有的dp[i]
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
using pii = pair<int, int>;
const int dr[5] = {0, -1, 1, 0, 0};
const int dc[5] = {0, 0, 0, -1, 1};
void solve() {int H, W, K;cin >> H >> W >> K;vector<int> dp(H * W, INF);vector<char> g(H * W, 0);for (int i = 0; i < K; i++) {int r, c;cin >> r >> c;--r, --c;int id = r * W + c;g[id] = 1;dp[id] = 0;}auto fun = [&](int r, int c) { return r >= 0 && r < H && c >= 0 && c < W; };priority_queue<pii, vector<pii>, greater<>> pq;for (int i = 0; i < H * W; i++) {if (g[i])pq.emplace(0, i);}while (!pq.empty()) {auto [cost, id] = pq.top();pq.pop();if (cost > dp[id])continue;int r = id / W, c = id % W;for (int dir = 1; dir <= 4; dir++) {int nr = r + dr[dir], nc = c + dc[dir];if (!fun(nr, nc))continue;int ni = nr * W + nc;int d[4];for (int i = 0; i < 4; i++) {int ar = nr + dr[i + 1], ac = nc + dc[i + 1];if (fun(ar, ac))d[i] = dp[ar * W + ac];elsed[i] = INF;}int m1 = INF, m2 = INF;for (int i = 0; i < 4; i++) {if (d[i] < m1) {m2 = m1;m1 = d[i];} else if (d[i] < m2) {m2 = d[i];}}int w = 0;for (int i = 0; i < 4; i++) {int k = (d[i] > m1 ? m1 : m2);w = max(w, k);}int c = w >= INF ? INF : w + 1;if (c < dp[ni]) {dp[ni] = c;pq.emplace(c, ni);}}}long long ans = 0;for (int x : dp) {if (x < INF)ans += x;}cout << ans << '\n';
}
int main() {solve();return 0;
}
G - Big Banned Grid
Problem Statement
There is an H×W grid. Let (i,j) denote the cell at the i-th row (1≤i≤H) from the top and j-th column (1≤j≤W) from the left.Each cell in the grid either has an obstacle placed on it or has nothing placed on it. There are K cells with obstacles: cells (r1,c1),(r2,c2),…,(rK,cK).
Takahashi is initially at cell (1,1) and wants to reach cell (H,W) by repeatedly moving to an adjacent cell (up, down, left, right) that has nothing placed on it.
More precisely, he can repeat the following operation as many times as he likes:
Choose one of the following four operations and perform the chosen operation:
If 1<i and cell (i−1,j) has nothing placed on it, move to cell (i−1,j). Otherwise, do not move.
If 1<j and cell (i,j−1) has nothing placed on it, move to cell (i,j−1). Otherwise, do not move.
If i<H and cell (i+1,j) has nothing placed on it, move to cell (i+1,j). Otherwise, do not move.
If j<W and cell (i,j+1) has nothing placed on it, move to cell (i,j+1). Otherwise, do not move.
Determine whether he can move from cell (1,1) to cell (H,W).
解题思路:
如果有一条线能将(1,1)和(H,W)在网格中分割成两个独立的块, 两点就无法形成通路
实现上, 我们可以,
为四个边界创建虚拟节点(编号k到k+3):
k:上边界(x=1)
k+1:下边界(x=n)
k+2:左边界(y=1)
k+3:右边界(y=m)
如果障碍物在边界上,将其与对应虚拟节点合并
遍历每个障碍物,检查它的8个方向(上下左右+对角线)
如果邻域存在其他障碍物,合并它们的集合
最后, 如果存在下面四种情况就说明两点被隔断了
上边界和下边界连通(k和k+1)
上边界和左边界连通(k和k+2)
左边界和右边界连通(k+2和k+3)
下边界和右边界连通(k+1和k+3)
#include <bits/stdc++.h>
using namespace std;
class UnionFind {vector<int> fa, sz;
public:int cc;UnionFind(int n) : fa(n), sz(n, 1), cc(n) { iota(fa.begin(), fa.end(), 0); }int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }bool merge(int x, int y) {x = find(x), y = find(y);if (x == y)return false;if (sz[x] > sz[y])swap(x, y);fa[x] = y;sz[y] += sz[x];cc--;return true;}
};
void solve() {int n, m, k;cin >> n >> m >> k;map<pair<int, int>, int> mp;vector<pair<int, int>> p(k);UnionFind uf(k + 5);for (int i = 0; i < k; i++) {cin >> p[i].first >> p[i].second;mp[p[i]] = i;if (p[i].first == 1)uf.merge(i, k);if (p[i].first == n)uf.merge(i, k + 1);if (p[i].second == 1)uf.merge(i, k + 2);if (p[i].second == m)uf.merge(i, k + 3);}for (int i = 0; i < k; i++) {int x = p[i].first, y = p[i].second;for (int dx = -1; dx <= 1; dx++) {for (int dy = -1; dy <= 1; dy++) {if (dx == 0 && dy == 0)continue;auto it = mp.find({x + dx, y + dy});if (it != mp.end()) {uf.merge(i, it->second);}}}}bool ans = uf.find(k) == uf.find(k + 1) || uf.find(k) == uf.find(k + 2) ||uf.find(k + 2) == uf.find(k + 3) ||uf.find(k + 1) == uf.find(k + 3);cout << (ans ? "No" : "Yes") << '\n';
}
int main() {solve();return 0;
}
感谢大家的点赞和关注,你们的支持是我创作的动力!