這是一份APCS中高級的複習講義,雖然不是我做的就是了。因為現在的AI很方便,所以我用AI做出了講義,之後應該也會詳細說明一下關於AI的事情,這份講義如果有語法不通的情況,歡迎各位聯絡我修正。
01 考制與達標策略
一、新制考試內容(114 學年度起)
| 程式識讀 | 程式實作 | |
|---|---|---|
| 題數 | 30 題單選 | 3 題 |
| 時間 | 90 分鐘 | 120 分鐘 |
| 滿分 | 100 分 | 300 分(每題 100 分) |
| 題本 | 選「C」或「Python」(你選 Python) | 選「初/中/中高/高級」(你選中高級) |
| 語言 | 依題本 | C、C++、Java、Python 自由選(你選 Python) |
識讀題型(官方公告):程式運行追蹤、程式填空、程式測試與除錯、程式效能分析、計算邏輯解析。 識讀範圍:資料型態、控制結構、函式、遞迴、陣列串列、堆疊佇列、排序與搜尋。
中高級題本範圍(官方公告,=你實作卷的全部考點):
- 函式、遞迴
- 佇列、堆疊
- 簡單樹(二元樹等)
- 簡單圖(網格 grid 等)
- 枚舉、資料遍歷
- 搜尋(二分搜尋、DFS 等)
二、級分對照(官方成績說明)
| 級分 | 程式識讀 | 程式實作(依題本) |
|---|---|---|
| 5 | 90 ~ 100 | 高級題本:150 ~ 300 |
| 4 | 70 ~ 89 | 高級:100 ~ 149|中高級:150 ~ 300 |
| 3 | 50 ~ 69 | 中高級:100 ~ 149|中級:150 ~ 300 |
| 2 | 30 ~ 49 | 中級:100 ~ 149|初級:150 ~ 300 |
| 1 | 0 ~ 29 | 其餘分數區間 |
關鍵解讀:
- 你考中高級題本:≥150 分拿 4 級分(上限即 4 級分);100~149 只有 3 級分。
- 識讀要 5 級分=100 分中最多錯約 3 題(以每題約 3.3 分估);70 分=可錯約 9 題。
三、2026/11/01 當日時程(官方)
| 時段 | 內容 |
|---|---|
| 13:00 入場|13:10 開始 | 程式識讀 90 分鐘(13:40 起可提前交卷) |
| 14:40 | 識讀結束,休息 30 分鐘 |
| 15:10 入場|15:20 開始 | 程式實作 120 分鐘(15:50 起可提前交卷) |
| 17:20 | 結束 |
成績查詢:2026/11/13 起(官網「查詢成績」)。
四、得分數學:4 級分怎麼湊
實作滿分 300、門檻 150。三題通常由易到難,穩健配速:
| 策略 | 配分 | 說明 |
|---|---|---|
| 基礎盤 | 第 1 題全對 = 100 | 通常是模擬/字串題,慢讀題目、務必一次 AC |
| 主力 | 第 2 題全對 = 100 | 資料結構應用(stack/queue/二分搜/枚舉),是你的訓練核心 |
| 保險 | 第 3 題部分分 ≥ 30 | 即使只會暴力法,先撈小測資分數 |
| 合計 | ≥ 230 | 遠超 150,容錯空間大 |
即使第 2 題卡住,100(第1題)+50(第2題部分)=150 也剛好達標 → 雙保險。 識讀與實作之間有 30 分鐘休息:上廁所、吃小點心、不要與人對答案。
五、考古題的真實狀況(重要觀念)
- 官方明文:不公告測驗試題及解答。市面上「考古題」都是考生憑記憶流傳的重建版(AA 競程亦如此聲明),官方唯一公開的是「題目範例」PDF。
- 所以練習策略=官方範例卷定錨+舊制歷屆練題量。舊制雖是 4 題 150 分鐘,但題目本質相同,AA 競程已把舊題標好「初/中/中高/高級」難度,直接篩「中高級」練就是最接近你考卷的題目。
六、考場環境(Python 考生必讀)
- 作業系統 Ubuntu 22.04,Python 3.10.12,編輯器:IDLE、vi/vim、leafpad(沒有 VSCode!)
- 執行方式:
python a.py(無特殊參數) - 平日練習請至少熟悉:IDLE 開新檔 → 貼上/撰寫 → F5 執行 → 用終端機餵輸入
python a.py < in.txt - 官方提供一模一樣環境的練習虛擬機(官網「系統環境」頁 → 安裝練習環境:VirtualBox + ISO),考前至少完整模擬一次
- 標準函式庫(collections、heapq、bisect、itertools、math)皆可用;第三方套件不可用
七、相關連結
02 程式識讀攻略(Python 題本,30 題 / 90 分鐘)
目標:5 級分 = 90 分以上(最多錯約 3 題);保底 4 級分 = 70 分(可錯約 9 題)。 配速:每題平均 3 分鐘,但不要平均用——用下面的三輪掃題法。
一、三輪掃題法
| 輪次 | 時間 | 做什麼 |
|---|---|---|
| 第 1 輪 | 前 30 分 | 從頭掃到尾,秒殺所有「一眼會」的題目(約 12~15 題);跳過的題號圈起來 |
| 第 2 輪 | 中間 45 分 | 攻 tracing/填空等中難度題;一道題超過 5 分鐘沒頭緒就先猜一個寫在題卷上,繼續走 |
| 第 3 輪 | 最後 15 分 | 回頭攻最難的 3~5 題;最後 3 分鐘確認每題都有作答(單選不倒扣,絕不留白) |
二、五大題型對策
1. 程式運行追蹤(code tracing,占比最高)
表格追蹤法:畫一張表,每個變數一欄,逐行更新,不要心算。
- 迴圈題:發現數值開始循環 → 找週期,直接跳到目標輪次。
- 兩層迴圈:外層跑前 3 輪找規律,再推總結果。
- 遞迴題:畫呼叫樹(見下方示範)。
def f(n):
if n <= 1:
return n
return f(n-1) + f(n-2) * 2
求 f(4):畫樹
f(4)
/ \
f(3) f(2)
/ \ / \
f(2) f(1) f(1) f(0)
/ \
f(1) f(0)
由下往上帶回:f(0)=0, f(1)=1, f(2)=1+02=1, f(3)=1+12=3, f(4)=3+1*2=5。 規則:先把所有 base case 填進樹葉,再由下往上合併。
2. 程式填空(code completion)
代入法:把每個選項代進去,用題目給的小測資跑一次。優先檢查:
- 迴圈邊界(
range(n)到n-1;range(1, n)少了第 0 個) - 初始值(=0 還是 =1;空字串還是空串列)
3. 程式測試與除錯(code testing and debugging)
問「哪個輸入會讓程式出錯/哪一行有 bug」時,專打邊界:
- 空串列、只有 1 個元素、全部相同元素、負數、0
- 交換變數、累加器放錯迴圈層、
<=誤寫< - 除錯順序:先看迴圈邊界 → 再看初始化 → 最後看邏輯
4. 程式效能分析(code performance analysis)
數迴圈層數即可,常見對應背下來:
| 程式形態 | 複雜度 | n=10^5 時 |
|---|---|---|
| 單層迴圈 | O(n) | 快 |
| 排序 | O(n log n) | 快 |
| 兩層巢狀 | O(n²) | ~10^10 步,太慢 |
| 二分搜 | O(log n) | 極快 |
「哪段程式比較快」題型:數巢狀深度;「輸入變大會不會超時」題型:n 超過 10^4 還用雙層迴圈 → 會。
5. 計算邏輯解析(computational logic analysis)
布林運算題:列真值表(最多 3 變數 8 列,直接寫完逐一驗證選項)。
化簡口訣:A and (A or B) = A、A or (A and B) = A、not (A and B) = not A or not B。
三、Python 題本高頻陷阱 15 條(考前必背)
- 別名陷阱:
b = a(a 是 list)後改b[0],a[0]也變 → list 是參照;b = a[:]才是複製。 - 函式預設參數只建立一次:
def f(x, acc=[])的 acc 會跨呼叫累積 → 陷阱題最愛。 - 可變物件當引數:函式內
lst.append()會影響外部;但lst = lst + [x]不會(建立新物件)。 5 / 2 = 2.5(真除法)、5 // 2 = 2(整除)、-5 // 2 = -3(向無窮小取整!)。- 字串不可變:
s[0] = "x"會出錯;s = s + "x"是建立新字串。 s[1:4]取 index 1,2,3(不含 4);s[::-1]反轉;切片超界不報錯,直接截斷。range(3)= 0,1,2;range(5, 0, -1)= 5,4,3,2,1(不含 0)。sorted(lst)回傳新串列;lst.sort()原地排序回傳 None →lst = lst.sort()是陷阱!- 迴圈中改變正在遍歷的 list/dict → 行為詭異或出錯,考題喜歡問「會輸出什麼」。
is比的是同一個物件,==比的是值相等;小整數快取(-5~256)會讓is意外為 True。and/or有短路且回傳「運算元」:0 or 5= 5、3 or 5= 3、0 and 5= 0。- 巢狀函式讀外層變數可以,賦值需要
nonlocal/global,否則視為新區域變數。 list * 2是元素重複([1,2]*2 = [1,2,1,2]),不是逐元素乘。- f-string 與
%、str()的輸出格式差異;round(2.5) = 2(銀行家捨入!)。 - 字典:同一 key 重複賦值只留最後一個;
dict.keys()順序=插入順序(3.7+)。
四、每日練習素材
| 天數 | 素材 |
|---|---|
| 每天 15~20 題 | AA 競程「程式識讀」線上卷 https://apcs.aacpoj.com/reading/(含官方 C/Python 範例+吳邦一 125 題模擬卷,交卷立刻看分數與解析) |
| 加強題量 | 吳邦一《APCS Python 程式識讀 125 題》PDF(題解目錄頁可下載 https://hackmd.io/@bangyewu/B13lefwMp) |
| 考前 | 只重做錯題本+上面 15 條陷阱 |
錯題本格式(每錯一題記一行):
日期|題號|題型|錯因(陷阱編號/沒看懂題意/追蹤失誤)|一句話教訓
五、自我檢核
- 計時 90 分鐘做官方「Python 題本範例卷」能拿 90+?
- 15 條陷阱能說出 12 條以上?
- 遞迴題能 2 分鐘內畫出 4~5 層呼叫樹?
- 三輪掃題法在模擬中執行過至少 2 次?
若你報名的是 C 題本而非 Python:陷阱清單換成 C 的(
++i與i++、字元'0'與數字 0、陣列未初始化、scanf/&、整數溢位、短路求值),題型對策完全相同。
03 實作題 Python 模板與基本功(中高級題本)
考場:Ubuntu 22.04 + Python 3.10.12,編輯器 IDLE / vim / leafpad,無第三方套件。 本檔案的模板請在 W1 內練到「默打」程度。
一、輸入輸出模板(最重要)
APCS 輸入格式多變,萬用讀法:把全部輸入一次讀進來再切片。
import sys
def main():
data = sys.stdin.read().split() # 依空白(含換行)切好
idx = 0
n = int(data[idx]); idx += 1
nums = [int(x) for x in data[idx:idx+n]]; idx += n
# ... 解題 ...
print(" ".join(map(str, nums))) # 一次輸出,別在迴圈裡 print
main()
四種常見輸入形態:
# A. 一個數字 n,之後 n 行、每行一個數字
nums = [int(x) for x in data[1:n+1]]
# B. 第一行 n m,之後 n 行每行 m 個數(網格/矩陣)
n, m = int(data[0]), int(data[1])
g = []
for i in range(n):
row = data[2+i*m : 2+(i+1)*m] # 字串
g.append([int(x) for x in row]) # 數字版
# C. 整行字串(含空格)→ 用 splitlines 取行
lines = sys.stdin.read().splitlines()
# D. 輸出多行:收集後一次印
out = []
out.append(str(ans))
print("\n".join(out))
規則:資料量大(≥10^5 個數字)一律用 sys.stdin.read();輸出量大用 join,不要迴圈內逐次 print。
二、常用工具箱(考場速查)
from collections import deque, Counter, defaultdict
import heapq, bisect, itertools, math
# 排序(多條件):先按第二欄升序、再按第一欄降序
items.sort(key=lambda x: (x[1], -x[0]))
# Counter:統計次數 / 找眾數
c = Counter("banana") # {'a':3,'n':2,'b':1}
c.most_common(1) # [('a', 3)]
# defaultdict:計數免判斷 key 存在
d = defaultdict(int); d[x] += 1
# deque:雙向佇列(BFS 必備)
q = deque([start])
while q:
cur = q.popleft()
q.append(nxt)
# heapq:最小堆
pq = []
heapq.heappush(pq, (cost, node))
cost, node = heapq.heappop(pq)
# 最大值堆:cost 取負號 push
# bisect:二分搜(list 需已排序)
a = [1, 3, 3, 5, 8]
bisect.bisect_left(a, 3) # 1 → 3 最左插入位置(=第一個 >=3 的位置)
bisect.bisect_right(a, 3) # 3 → 最後一個 3 的下一格
a[bisect.bisect_left(a, x)] == x # 判斷 x 是否存在
# itertools:枚舉神器
itertools.combinations([1,2,3], 2) # (1,2)(1,3)(2,3) 組合
itertools.permutations([1,2,3]) # 排列
itertools.product("ab", repeat=3) # 笛卡爾積(枚舉所有 0/1 串)
# 二維串列(別用 [[0]*m]*n !那是同一列的別名)
grid = [[0]*m for _ in range(n)]
# 數學
math.gcd(12, 18) # 6
math.isqrt(17) # 4(整數開根號)
divmod(17, 5) # (3, 2)
三、Python 效能守則(避免 TLE)
| 原則 | 說明 |
|---|---|
| 心算預算 | Python 每秒約 10^6~10^7 個基本操作;n=10^5 時只能接受 O(n log n),O(n²) 必死 |
| 讀入 | sys.stdin.read().split() 一次讀完 |
| 輸出 | "\n".join() 一次寫 |
| 成員判斷 | 大量 in 用 set(O(1)),別對 list 做(O(n)) |
| 字串累加 | 用 list 收集再 join,不要 s += x 迴圈 |
| 遞迴深度 | 預設上限 1000 → 程式開頭 sys.setrecursionlimit(300000);深度可能破萬時改迭代寫法 |
四、遞迴與迭代 DFS
# 遞迴版 DFS(深度淺時好用)
def dfs(u, parent):
visited[u] = True
for v in adj[u]:
if not visited[v]:
dfs(v, u)
# 迭代版 DFS(深度深、防爆棧)
def dfs_iter(start):
stk = [start]
while stk:
u = stk.pop()
if visited[u]:
continue
visited[u] = True
for v in adj[u]:
if not visited[v]:
stk.append(v)
五、提交策略與部分分(子題制)
- 每題依「通過測資比例」給分 → 小測資通常資料範圍小(如 n≤1000),暴力法就能拿。
- 流程:讀完題 → 40 分鐘內想不出有效解 → 先寫暴力版提交鎖分 → 再回來優化。
- 作答系統可提交多次(以現場說明為準),先交一版保底,之後持續改進覆蓋。
- 暴力版範式:能枚舉就枚舉(
itertools)、能雙層迴圈就雙層——先求對、再求快。
六、除錯 checklist(WA / TLE / RE 對症下藥)
WA(答案錯)
- 輸出格式:行末多餘空格?大小寫?要不要換行?
- 邊界:n=1、空輸入、全相同、最大值
- 型別:該
int()的有轉嗎?整數除法//與/用對嗎? - 讀錯題:重讀一遍題目「輸出」段落(最常見死因!)
TLE(超時)
- 複雜度:雙層迴圈 × n=10^5 → 重寫(排序/二分/set/前綴和)
- I/O:改
sys.stdin.read()、join 輸出 - 迴圈內呼叫函式過多 → 展開或局部化變數
RE(執行錯誤)
- 陣列越界(index 從 0 還是 1?最後一格?)
- 遞迴深度 →
setrecursionlimit或改迭代 - 除以 0、對空串列
max()/pop()
七、本地測試法(考前練熟)
1. 存成 a.py,輸入存成 in.txt
2. 終端機:python a.py < in.txt
3. 對照題目範例輸出(含行數、空格)
4. 自造邊界測資:最小輸入、最大輸入各測一次
考場沒有自帶測資檔時,直接在作答系統提交,看它對範例測資的判定。
04 中高級題型突破(對應官方檢測範圍)
官方中高級範圍:函式/遞迴、佇列/堆疊、簡單樹、簡單圖(網格)、枚舉/遍歷、搜尋(二分/DFS)。 每個主題給你:識別訊號 → 解題 SOP → 模板 → 練習。練習題到 AA 競程考古題(https://apcs.aacpoj.com/past/)篩「中高級」難度,或直接提交舊制題號。
主題 1:流程模擬(中高級卷第 1 題的常客)
識別訊號:題目敘述一堆規則叫你照做(行走、翻轉、計分、狀態變化)。 SOP:
- 逐句讀規則,把每條規則翻譯成一行註解(考場用草稿紙)
- 注意「同時發生」還是「依序發生」(同時 → 先算完再更新)
- 邊界:第一步/最後一步、出界、重複事件
心法:模擬題不考演算法,考「細心」。慢讀 5 分鐘題目,寫 20 分鐘程式。
練習:2023-06 第 1 題〈路徑偵測〉ZeroJudge
k731;2023-06 第 2 題〈特殊位置〉k732(題解見吳邦一目錄 HackMD)。
主題 2:字串與字元處理
識別訊號:輸入是文字(密碼、編碼、句子、基因序列),要解析/變換/比對。
關鍵工具:split / join / strip / replace / find / count / startswith、ord() / chr()、切片。
# 大小寫、字母判斷
ch.isupper(); ch.isdigit(); ch.isalpha()
s.lower(); s.upper()
# 依多個分隔符切字串
import re; re.split("[,; ]+", s) # 或 s.replace(";", ",").split(",")
# 迴文判斷
s == s[::-1]
心法:字串題先問自己「要不要保留原始字串」→ 要就先 t = s[:]。
練習:AA 競程中高級難度篩「字串」類;官方中級範例卷也值得練(字串是中級主軸,中高級仍會考)。
主題 3:遞迴與枚舉
識別訊號:
- 遞迴:「定義本身就是小的自己」(費氏、切割、走法數、運算式展開)
- 枚舉:「所有可能不大」(n ≤ 20 的組合、要找最佳選擇但範圍小)
# 遞迴骨架:先寫終止條件,再寫遞推
def solve(state):
if 終止條件:
return base_answer
return 合併(solve(下一狀態1), solve(下一狀態2))
# 枚舉子集合(選/不選)
def gen(i, chosen):
if i == n:
check(chosen) # 驗證、計分
return
gen(i+1, chosen + [a[i]]) # 選
gen(i+1, chosen) # 不選
搭配 itertools.combinations / permutations / product(見 04 工具箱)。
心法:先估可能數量——n=20 子集合 2^20≈10^6(可行),n=40 就別枚舉了。
練習:2023-06 第 4 題〈開啟寶盒〉k734(挑戰);吳邦一「2024.10 / 2025.01 實作題解」中的枚舉型題。
主題 4:堆疊 stack 與佇列 queue
識別訊號:
- stack:配對/巢狀(括號、HTML 標籤)、上一個/下一個更大元素、「撤銷」
- queue:排隊、輪流處理、BFS(見主題 5)
# 括號配對(stack 經典)
def ok(s):
pair = {')':'(', ']':'[', '}':'{'}
stk = []
for ch in s:
if ch in "([{":
stk.append(ch)
elif not stk or stk.pop() != pair[ch]:
return False
return not stk
心法:stack 就是 list.append()/pop();queue 就是 deque.popleft()。
練習:AA 競程中高級篩選;官方中高級範例卷若有 stack 題必做兩遍。
主題 5:網格圖(grid)DFS / BFS
識別訊號:輸入是 n×m 的地圖/矩陣;問「連通塊數量」「能不能走到」「最少步數」「被包圍的區域」。
# BFS 最短步數模板(背到滾瓜爛熟)
from collections import deque
def bfs(sx, sy):
dist = [[-1]*m for _ in range(n)]
dist[sx][sy] = 0
q = deque([(sx, sy)])
while q:
x, y = q.popleft()
for dx, dy in ((1,0),(-1,0),(0,1),(0,-1)):
nx, ny = x+dx, y+dy
if 0 <= nx < n and 0 <= ny < m and dist[nx][ny] == -1 and g[nx][ny] != '#':
dist[nx][ny] = dist[x][y] + 1
q.append((nx, ny))
return dist
- 連通塊數量:每個沒拜訪過的格子起點做一次 BFS/DFS 並標記。
- 最少步數:BFS(權重都一樣時 BFS 就是最短路)。
- DFS 也行,但求「最短」時必須 BFS。 練習:AA 競程「站外練習」CSES 題單的網格題(中文題敘);吳邦一「2023.10 / 2024.06 題解」中的地圖題。
主題 6:樹(二元樹與一般樹)
識別訊號:輸入 n-1 條邊(或每個節點的父節點);問深度/高度、子樹大小、前中後序、層序。
# 用父節點陣列建樹 + 求每點深度
n = len(parent)
children = [[] for _ in range(n)]
for v in range(1, n):
children[parent[v]].append(v)
depth = [0]*n
order = [0] # 由上往下算(根為 0)
while order:
u = order.pop()
for v in children[u]:
depth[v] = depth[u] + 1
order.append(v)
# 前序/中序/後序(遞迴版,二元樹)
def pre(u): # 根左右
if u is None: return []
return [u] + pre(L[u]) + pre(R[u])
心法:樹題 90% = 「怎麼存樹」+「用哪種遍歷」。存法只有兩種:children 鄰接表、parent 陣列。 練習:吳邦一「2024.01 / 2025.06 題解」中的樹題;AA 競程中高級篩選。
主題 7:二分搜尋(含「答案二分」)
識別訊號:
- 「排好序的資料中找位置/找第一個 ≥ x」「差距最小化」→
bisect - 「最大化最小值/最小化最大值」「最少需要多少」→ 答案二分(對答案猜數字,用 check() 驗證)
# 答案二分模板(可行/不可行具有單調性)
lo, hi = 0, 10**18 # 答案的可能範圍
while lo < hi:
mid = (lo + hi) // 2
if check(mid): # mid 可行 → 試著更小/更大
hi = mid
else:
lo = mid + 1
print(lo)
心法:bisect 處理「在序列裡找」;答案二分處理「在數值範圍裡找」。check() 只需要「驗證某個答案行不行」,通常一層迴圈寫完。
練習:AA 競程中高級篩選;CSES 題單搜尋章節(站外練習區)。
綜合練習指引(W2~W3 的題單來源)
| 來源 | 用法 |
|---|---|
| AA 競程考古題(篩中高級) | 主力。每天 1 題、計時 40 分鐘,寫完看 59 題內的官方收錄題解 |
| ZeroJudge APCS 標籤 | 補充題量:https://zerojudge.tw/Problems?tag=APCS |
| 吳邦一歷屆題解(C+++Python) | 對答案用:2023.10、2024.01、2024.06、2024.10、2025.01、2025.06 各場(從目錄 https://hackmd.io/@bangyewu/B13lefwMp 進入) |
| AP325-Python 講義 | 想系統性補某主題時翻對應章節:https://hackmd.io/@bangyewu/Hy2kbYLI6 |
| piaublog 歷屆解析 | 看不懂某題時的第二種解法視角:https://piaublog.com/apcs-guide/past-problems/ |
每題做完後的自問(30 秒檢討法)
- 我多久看出這是哪個主題?(→ 練識別訊號)
- 卡住最久的行是哪一行?(→ 語法?邊界?思路?)
- 題解有沒有更短寫法?(→ 收進
04模板檔)
05 模擬考執行、檢討與考前檢查
模擬考是這 26 天裡投資報酬率最高的活動。目標不是分數好看,是把流程練成反射。
一、模擬考排程
| 場次 | 日期 | 素材 | 備註 |
|---|---|---|---|
| 診斷 | 10/6~10/7 | 官網範例卷(識讀 Python+實作中高級) | 建立弱點地圖 |
| #1 | 10/17 六 | AA 競程「模擬測驗」(計時)https://apcs.aacpoj.com/mock/ | 實作 120 分+識讀 90 分 |
| #2 | 10/24 六 | AA 競程「模擬測驗」另一場 | 照真實時段:13:10 識讀、15:20 實作 |
| #3 | 10/29 四 | 識讀全真(30 題/90 分)+實作 1 題 40 分限時 | 量小,維持手感 |
二、模擬考 SOP(照正式考執行)
- 環境:關手機、只開 IDLE(或 AA 競程作答介面)、計時器放旁邊。
- 識讀 90 分:執行三輪掃題法(見
03);留最後 3 分鐘檢查有無漏答。 - 實作 120 分:每題時間上限 40 分鐘;20 分鐘沒進展先寫暴力版提交;中間不看任何資料。
- 中途禁止:查語法、看題解、暫停計時。(忘記語法=真實考場也會忘,記下來就是弱點)
三、檢討表(每次模擬考後 30 分鐘內填)
| 題號 | 結果 | 失分原因(選一) | 具體教訓一句話 |
|---|---|---|---|
| 例:實作 P2 | 部分分 60 | 邊界(n=1) | 二維陣列先想清楚 index 從 0 開始 |
失分原因六分類:讀錯題意/邊界與特殊值/演算法想不到/複雜度超時/語法不熟/輸出格式。 同一分類出現 2 次以上 → 下週排一天專攻它。
四、考前 3 天(10/29~10/31)
- 錯題本全部過一遍(識讀陷阱 15 條、實作 checklist)
- 默打三大模板:
sys.stdin.read()萬用讀入、grid BFS、答案二分 - 考場環境預演:用官方練習 VM(官網「系統環境」頁下載)或至少用 IDLE 跑一題完整流程
- 10/30 只複習、不練新題、不熬夜;10/31 21:30 前睡
五、考前一夜裝備清單
- 身分證件+准考證(依官網報名規定)
- 2B 鉛筆、橡皮擦、黑色筆(識讀若有紙本劃卡依簡章規定;草稿一定用得到)
- 透明墊板、水(無標籤瓶裝)、小點心(中場 30 分鐘吃)
- 查好試場位置與交通(10/26 起官網可查應試試場)
- 手機鬧鐘 ×2(最晚 12:30 起床族請自行調整)
六、考試當日流程(11/1 日)
| 時間 | 行動 |
|---|---|
| 上午 | 正常吃早餐;考前不再學新東西,只翻錯題本 |
| 12:45 | 抵達試場報到 |
| 13:00 | 入場就座,測試電腦(開 IDLE 打一段Hello World 熟鍵盤) |
| 13:10~14:40 | 識讀:三輪掃題法;全卷不留白 |
| 14:40~15:10 | 休息:上廁所、吃點心、深呼吸;不與人對答案 |
| 15:10 | 入場,準備好草稿紙 |
| 15:20~17:20 | 實作:15 分鐘讀完三題(先挑最有把握的開刀)→ 40 分/題上限 → 每完成一題立即提交鎖分 |
| 17:00 | 若提前做完:用剩餘測資想法檢查邊界,不要大改已 AC 的程式 |
七、實作答題決策樹(背起來)
讀完一題 → 想到有效解?
├─ 是 → 直接寫(估複雜度:n=10^5 別用雙層迴圈)
└─ 否 → 這題的小測資(子題)能不能暴力拿分?
├─ 能 → 30 分鐘內先交暴力版鎖分,之後有時間再升級
└─ 不能 → 換題。最後真的沒題可寫 → 寫「能拿部分分的任何東西」
八、成績與下一步
- 2026/11/13 開放查詢成績(官網「查詢成績」)
- 若實作拿到 4 級分但想拚 5 級分:需考「高級題本」,近期場次見官網場次資訊(https://apcs.csie.ntnu.edu.tw/index.php/importantdates/),2027 年 3 月場次預計有中高級與高級題本
- 成績可用於申請入學備審與特殊選才;採計校系查詢:官網「採計成績大學校系」
06 解題思維:從「看到題目」到「知道怎麼寫」
你的狀況:模板都會,但看到題目不知道從何下手。 這不是演算法問題,是翻譯問題——APCS 題目 95% 是「把中文規則翻譯成資料結構操作」。 你缺的不是更多模板,是**「辨認這題該翻譯成哪個模板」的反射神經**。本檔案就是練這個。
一、核心心法:解題 = 三個轉換
中文題目 ──①審題拆解──> 「問什麼 + 有什麼 + 規則是什麼」
──②識別套路──> 「這是 __ 型題目」
──③翻譯成碼──> 「資料結構 + 迴圈 + 模板」
卡住的時候,先問自己卡在哪一層:讀不懂題?(①)不知道用什麼方法?(②)知道方法寫不出來?(③→回 04 模板檔)。多數人卡在②,而②是可以用「訊號詞對照表」直接命中練出來的。
二、五步審題法(每題固定走一遍,約 5 分鐘)
| 步驟 | 動作 | 你要得到的東西 |
|---|---|---|
| 1. 先讀最後一段 | 看「輸出說明」,不看成敘過程 | 答案型態:一個最值?一個數量?模擬結果?判斷可否?一串查詢? |
| 2. 看資料範圍 | 輸入說明的 n、m 最大值 | 複雜度預算(見第三節表)→ 直接淘汰 80% 的笨方法 |
| 3. 劃規則句 | 圈出「每次/依序/同時/不能/必須」開頭的句子 | 這些就是要翻譯的規則;「同時」= 先算完再更新,「依序」= 邊走邊更新 |
| 4. 手跑範例 | 拿範例輸入在草稿紙當電腦跑一遍 | 驗證你理解正確+通常會看到規律 |
| 5. 寫 3~5 行偽代碼 | 中文寫:讀入 → 初始化 → 對每個○○做□□ → 輸出 | 翻譯成 Python 只是體力活 |
黃金規則:先想清楚「資料要存成什麼形狀」(一個數?一維陣列?二維網格?字典?),存對了,程式就寫對一半。
三、資料範圍 → 演算法對照表(倒推法,Python 保守版)
| 題目給的規模 | 可接受的複雜度 | 能用的手法 |
|---|---|---|
| n ≤ 100 | O(n³) | 三層迴圈硬暴力 |
| n ≤ 5,000 | O(n²) | 雙層迴圈、兩兩配對、暴力枚舉 |
| n ≤ 100,000 | O(n log n) | 排序、二分搜、heap、單次掃描 |
| n ≤ 1,000,000 | O(n) | 前綴和、計數、一次掃描 |
| n ≤ 10⁹(或答案很大) | O(log n) | 二分答案、數學公式 |
| 地圖 n×m ≤ 10⁶ 格 | O(nm) | BFS / DFS |
| n ≤ 20 | O(2ⁿ) | 全枚舉(選/不選) |
用法示範:題目說 n ≤ 200,000 → 查表 → 只能 O(n log n) 以下 → 「排序+掃描」或「二分」→ 雙層迴圈想都不用想(直接省下 10 分鐘)。
四、訊號詞對照表(②的答案,背到看到字就反射)
| 題目出現的關鍵字 | 題型 | 第一步動作 |
|---|---|---|
| 「依照以下規則」「執行指令」「每一步」 | 模擬 | 把規則逐句翻譯成程式行,狀態用變數存 |
| 地圖/棋盤+「走」「移動」「相鄰」 | 網格圖 | 讀成二維陣列 → 想 BFS/DFS |
| 「最少步數」「最短時間」「能不能走到」 | BFS 最短路 | BFS 模板+距離陣列 |
| 「連通的區域」「有幾塊」「被包圍」 | flood fill | 對每個沒標記的格子 DFS/BFS 標記 |
| 「括號」「配對」「巢狀」「上一個比它大的」「撤銷」 | stack | list.append() / pop() |
| 「排隊」「輪流」「每隔 k 個淘汰」 | queue | deque.popleft() |
| 「第 k 大」「前 k 個」「按○○排序後」 | 排序 | sort(key=...) 後掃描 |
| 「每次都選當前最好的」「最多能容納幾個」 | 貪心 | 先排序,想清楚「按哪個欄位排」再證明 |
| 「最小的最大值」「最大的最小值」「最快多久」「最少幾個○○才夠」 | 二分答案 | 寫 check(T) 函數,二分 T |
| 「已排序的」「找第一個 ≥ x」「出現幾次」 | bisect | bisect_left / bisect_right |
| 「連續子陣列」「區間和」「和恰好為 x」 | 前綴和/滑動視窗 | prefix 陣列或雙指標 |
| 「所有組合」「選或不選」且 n ≤ 20 | 枚舉 | itertools 或遞迴枚舉 |
| 「父節點」「子節點」「深度」「走訪順序」 | 樹 | children 表+遍歷(05 主題6) |
| 「出現次數」「眾數」「成對刪除」 | 計數 | Counter / defaultdict(int) |
| 「兩兩之間的○○」且 n ≤ 5000 | 暴力配對 | 雙層迴圈,別想太多 |
| 「翻轉」「顛倒」「回文」 | 字串操作 | 切片 s[::-1] |
練法:這張表不是背文字,是背「字 → 動作」的直覺。每做完一題考古題,回頭對照:它的訊號詞是哪一個?沒對上就補一行進你的私人表格。
五、三道完整思考實錄(示範題為自創,風格仿 APCS)
示範 A:模擬題〈門禁管制〉
題目:大樓入口記錄了 n 筆事件(n ≤ 10⁵),每筆是 IN(進入一人)或 OUT(離開一人)。館內初始 0 人;若 OUT 時館內無人,該筆事件被忽略並計一次錯誤。請輸出最終館內人數與錯誤次數。
五步實錄:
- 問什麼?→ 輸出兩個數(人數、錯誤次數)。不是最值、不是搜尋 → 應該是模擬。
- 範圍?n ≤ 10⁵ → 查表:只能 O(n) → 一次掃描,雙層迴圈出局。
- 規則句:只有兩條(IN / OUT),「忽略並計錯誤」→ 需要一個錯誤計數器。
- 手跑範例
IN IN OUT OUT OUT IN:0→1→2→1→0→(OUT 時 0 人→忽略、錯誤+1)→1。輸出1 1✓ - 偽代碼:
people=0; err=0; 對每筆事件: IN→people+=1; OUT→ if people>0: people-=1 else: err+=1; 印出
import sys
data = sys.stdin.read().split()
n = int(data[0]); people = 0; err = 0
for i in range(1, n+1):
if data[i] == "IN":
people += 1
elif people > 0:
people -= 1
else:
err += 1
print(people, err)
學到的:模擬題的五步最快,核心是第 3 步把規則念成程式。「忽略」這種小字最容易漏。
示範 B:網格題〈停車場逃生〉
題目:n×m 地圖(n, m ≤ 1000),S 是你的位置(恰一個),E 是出口(可能多個),. 可走,# 是牆。每分鐘可上下左右移動一格。求到達任一出口的最少分鐘;到不了輸出 -1。
五步實錄:
- 問什麼?→「最少○○」+「能不能到」→ 查第四節表:「最少步數/能不能走到」→ BFS,命中。
- 範圍?1000×1000 = 10⁶ 格 → 查表:O(nm) 可行 → BFS 恰好 O(nm),匹配。
- 規則句:四方向、不能穿牆、多個出口任一個都行 → BFS 每格只進佇列一次,先到者距離最短(廣度優先的性質保證)。
- 手跑小地圖:畫 3×4,手動標出每格的步數 0,1,1,2…(就是 BFS 的層序)。
- 偽代碼:
從 S 開始 BFS;dist 記步數;遇到 E 就輸出 dist;佇列空了還沒遇到 → -1
import sys
from collections import deque
def main():
data = sys.stdin.read().split()
n, m = int(data[0]), int(data[1])
g = [data[2+i] for i in range(n)] # 每列字串直接當一維字元陣列用
for i in range(n):
for j in range(m):
if g[i][j] == "S":
sx, sy = i, j
dist = [[-1]*m for _ in range(n)]
dist[sx][sy] = 0
q = deque([(sx, sy)])
while q:
x, y = q.popleft()
if g[x][y] == "E":
print(dist[x][y]); return
for dx, dy in ((1,0),(-1,0),(0,1),(0,-1)):
nx, ny = x+dx, y+dy
if 0 <= nx < n and 0 <= ny < m and dist[nx][ny] == -1 and g[nx][ny] != "#":
dist[nx][ny] = dist[x][y] + 1
q.append((nx, ny))
print(-1)
main()
學到的:這題「想到 BFS」不需要天賦——是第 1 步(問最少)+第 2 步(範圍允許 O(nm))兩個線索疊出來的。套路是查表查到的,不是憑空想到的。
示範 C:二分答案〈影印店〉
題目:影印店有 k 台印表機(k ≤ 10⁵),第 i 台印一張需要 tᵢ 分鐘,所有機器可同時運轉。要印 n 張講義(n ≤ 10⁶),求最少需要幾分鐘。
五步實錄(含一段真實的彎路):
- 問什麼?→「最少幾分鐘」→ 最值題。
- 彎路:先想貪心「每張都給最快的機器印」?→ 不對,一台要連續印多張,時間會混在一起,沒有明顯的「每次選一個」結構。
- 轉念(關鍵技巧——猜答案):與其問「幾分鐘」,不如反問「如果給我 T 分鐘,印得完嗎?」→ 每台可印
T // tᵢ張,加總 ≥ n 就是印得完。這個 check 只需一層迴圈 O(k)! - 為什麼能二分?T 越大越印得完(單調性)→ 查表:「至少多久才夠」→ 二分答案。
- 範圍?check 是 O(k),二分 log(10¹⁴) ≈ 47 次 → 總共 4.7×10⁶ 次,穩。
import sys
def main():
data = sys.stdin.read().split()
n, k = int(data[0]), int(data[1])
t = [int(x) for x in data[2:2+k]]
def enough(T): # T 分鐘內印得完嗎?
return sum(T // ti for ti in t) >= n
lo, hi = 1, max(t) * n # 答案一定在這範圍內
while lo < hi:
mid = (lo + hi) // 2
if enough(mid):
hi = mid
else:
lo = mid + 1
print(lo)
main()
手驗範例:n=5, t=[1,3] → T=3 時 3//1+3//3=4 張(不夠),T=4 時 4+1=5(剛好)→ 答案 4。 學到的:**「不會直接算答案,就學會『驗證答案』。驗證容易+答案單調 = 二分答案。」**這是中高級卷 P2、P3 的常見考點。
六、完全沒頭緒時的急救五招(照順序試)
- 縮小法:「如果 n = 3 我會怎麼做?」把笨辦法寫出來——那就是暴力解,先拿部分分,再看能不能升級。
- 紙上模擬法:拿範例輸入自己當電腦跑一遍,注意「我剛剛做了什麼動作」——你手上的動作就是演算法。
- 倒推法:盯著輸出格式問「最終答案 = 什麼的和/最大值?」每一項能不能單獨算?
- 單調法:「給我更多時間/資源,會更容易達成嗎?」是 → 二分答案(示範 C 的招)。
- 保底法:20 分鐘仍沒頭緒 → 寫暴力版提交鎖部分分 → 換題(呼應
06的決策樹)。
七、把反射練出來:每天 10 分鐘「三分鐘分類」
每天挑 3 道考古題(AA 競程 → 考古題 → 篩中高級),只讀題、不解題,計時每題 3 分鐘,寫三行:
問什麼:最值/數量/模擬結果/可行性/一串查詢
範 圍:n = ____ → 允許 O(____)
套 路:我猜是 ____,因為訊號詞「____」
寫完再點開題解驗證猜對沒有。錯了就問自己:漏看了哪個字?把那個字補進第四節的私人表格。 這個練習是本講義最重要的部分:一周後你會發現 80% 的題目 30 秒內就能分類——「看到題目不知道怎麼應對」就是這樣消失的。
八、審題筆記模板(寫在每道題旁邊)
[題目代號] ______
問什麼:__________
範圍:n ≤ ____ → 預算 O(____)
訊號詞:__________
存什麼:____(變數/一維/二維/dict/deque)
偽代碼:
1. 讀入
2. ______
3. 對每個 ○○ 做 ______
4. 輸出 ______
[提交結果] AC/WA(原因:____)/TLE(原因:____)
