# APCS 2025/06 >C++ 版本由我本人 @Yilin0121 撰寫 >Python 版本由 @Chuen666666 提供 ## [1. 小心陷阱](https://zerojudge.tw/ShowProblem?problemid=q836) ### 思路 我們每次都會走k步,當k <= 0時就會結束,所以我們可以用while迴圈來寫,只要k > 0就重複執行,只要我們現在的位置是x1或x2的倍數,k就減掉y1或y2,最後算出的位置就是答案 ### 完整程式碼 #### C++ ```cpp= #include <bits/stdc++.h> using namespace std; #define IO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); const long long INF = numeric_limits<int>::max(); int main() { int k, x1, y1, x2, y2; cin >> k >> x1 >> y1 >> x2 >> y2; int now = k; while (k > 0) { if (now % x1 == 0) k -= y1; if (now % x2 == 0) k -= y2; now += max(0, k); } cout << now; } ``` #### Python ```python= k = int(input()) x1, y1 = map(int, input().split()) x2, y2 = map(int, input().split()) i = 0 while k > 0: i += k if i % x1 == 0: k -= y1 if i % x2 == 0: k -= y2 print(i) ``` ## [2. 轉盤得分](https://zerojudge.tw/ShowProblem?problemid=q837) ### 思路 記下每個字串的開始位置,扣掉每次的轉動距離,就是新的起點。 :::info C++的要特別注意善用(((i + pos[j]) % n) + n) % n,不然有可能是負數而Run-time error ::: ### 完整程式碼 #### C++ ```cpp= #include <bits/stdc++.h> using namespace std; #define IO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); const long long INF = numeric_limits<int>::max(); int main() { int m, n, k; cin >> m >> n >> k; vector<string> s(m); for (auto &x : s) cin >> x; vector<int> pos(m, 0); int ans = 0; while (k--) { for (int i = 0;i < m;i++) { int x; cin >> x; pos[i] -= x; } for (int i = 0;i < n;i++) { int a[26] = {}, MAX = 0; for (int j = 0;j < m;j++) { MAX = max(MAX, ++a[s[j][(((i + pos[j]) % n) + n) % n] - 'a']); } ans += MAX; } } cout << ans; } ``` #### Python ```python= from collections import Counter m, n, k = map(int, input().split()) s = [input().strip() for _ in range(m)] pos = [0] * m total = 0 for _ in range(k): shifts = list(map(int, input().split())) for i in range(m): pos[i] -= shifts[i] for i in range(n): chars = [s[j][(i + pos[j]) % n] for j in range(m)] count = Counter(chars) total += max(count.values()) print(total) ``` ## [3. 貪心闖關](https://zerojudge.tw/ShowProblem?problemid=q838) ### 思路 我們用一個維持「嚴格遞減」的棧來模擬每次搬最小再把沙包加到右邊的過程:對於每個關卡的沙包數x,只要棧頂w≤x就表示它是當前最小的,按題意要先搬空它(把w加到答案),並把這批沙包累加到 x;反覆彈棧直到棧頂>x。此時,若合併後的x還不超過限制t,就把它當作新棧頂壓進棧中,保持棧的遞減性。全部讀完後,把棧中剩餘的沙包數一次性加到答案即得最終結果。 ### 完整程式碼 #### C++ ```cpp= #include <bits/stdc++.h> using namespace std; #define IO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); #define int long long const long long INF = numeric_limits<int>::max(); signed main() { IO int n, t; cin >> n >> t; vector<int> st; int ans = 0; for (int i = 0;i < n;i++) { int x; cin >> x; while (!st.empty() and st.back() <= x) { ans += st.back(); x += st.back(); st.pop_back(); } if (x <= t) st.push_back(x); } for (auto x : st) ans += x; cout << ans; } ``` #### Python ```python= n, t = map(int, input().split()) st = [] ans = 0 for _ in range(n): x = int(input()) while st and st[-1] <= x: ans += st[-1] x += st[-1] st.pop() if x <= t: st.append(x) print(ans + sum(st)) ``` ## [4. 分組遊戲](https://zerojudge.tw/ShowProblem?problemid=q839) ### 思路 我們先把整張圖畫出來,每個點之間都會有距離,那我們只要遍歷每個點,只要與其中一個點的距離小於m我們就把他們歸類為同一組,嘗試最多可以分成幾組,只要分出的組別大於k,代表可以成功地分出k組,所以我們只需要二分搜出m,就可以算出答案。 ### 完整程式碼 #### C++ ```cpp= #include <bits/stdc++.h> using namespace std; #define IO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); const long long INF = numeric_limits<int>::max(); int n, k; vector<vector<pair<int, int>>> v; bool f(int m) { bitset<505> vis; int cnt = 0; for (int i = 1;i <= n;i++) { if (vis[i]) continue; queue<int> q; cnt++; q.push(i); while (!q.empty()) { auto t = q.front(); q.pop(); for (auto [nt, x] : v[t]) { if (vis[nt]) continue; if (x >= m) continue; vis[nt] = 1; q.push(nt); } } } return cnt >= k; } int main() { IO cin >> n >> k; v.resize(n + 1); int l = INF, r = 0, ans; for (int i = 1;i <= n;i++) { for (int j = 1;j <= n;j++) { int x; cin >> x; if (i != j) v[i].push_back({j, x}); r = max(r, x); l = min(l, x); } } while (l <= r) { int m = (l + r) / 2; if (f(m)) { l = m + 1; ans = m; } else r = m - 1; } cout << ans; } ``` #### Python ```python= from collections import deque def f(m): vis = [False] * (n + 1) cnt = 0 for i in range(1, n + 1): if vis[i]: continue cnt += 1 q = deque([i]) while q: t = q.popleft() for nt, x in v[t]: if vis[nt] or x >= m: continue vis[nt] = True q.append(nt) return cnt >= k n, k = map(int, input().split()) v = [[] for _ in range(n+1)] l = float('inf') r = 0 for i in range(1, n+1): row = list(map(int, input().split())) for j in range(1, n+1): x = row[j-1] if i != j: v[i].append((j, x)) r = max(r, x) l = min(l, x) ans = -1 while l <= r: m = (l+r) // 2 if f(m): ans = m l = m + 1 else: r = m - 1 print(ans) ```