語法書 / AA 競程語法書 上冊 / 第五單元 / 全部判定結果詳解

5.3 全部判定結果詳解

程式上傳後,OJ 會給你一個判定結果。如果沒通過,這個結果能告訴你大概是哪裡出問題。理解每個結果,才能有效地除錯。

6 大判定結果

AC —— Accepted(接受)

代表什麼:你的程式對所有隱藏測資都答對了。

你該做的:恭喜!移到下一題。


WA —— Wrong Answer(答案錯誤)

代表什麼:程式編譯和執行都成功了,但對某筆測資的輸出和預期答案不一致。

常見原因

  • 演算法邏輯錯誤(核心問題解法本身有 bug)
  • 讀題不仔細(例如沒注意輸入格式或範圍)
  • 浮點數精度不足(算出來是 3.9999999 而不是 4.0)
  • 輸出格式不符(多了空格、少了換行等)
  • 邊界情況沒處理(0、負數、最大值、最小值等)

除錯方法

  1. 重新檢查演算法邏輯
  2. 用範例輸入在自己電腦上跑一遍,看結果對不對
  3. 檢查輸出格式是否完全符合題目要求
  4. 考慮有沒有遺漏的邊界情況

RE —— Runtime Error(執行時錯誤)

代表什麼:程式編譯通過了,但執行時遇到了致命錯誤,導致程式崩潰。

常見原因

  • 除以零int x = 10 / 0;
  • 陣列存取越界int arr[10]; arr[15] = 5;
  • 指標非法存取int* p = nullptr; *p = 10;
  • 堆疊溢位:遞迴太深或陣列定義太大
  • 非法記憶體釋放delete 同一個指標兩次

除錯方法

  1. 檢查所有除法操作,確保分母不為零
  2. 檢查陣列索引是否在範圍內
  3. 檢查遞迴深度是否過大
  4. 檢查動態記憶體分配是否正確

CE —— Compilation Error(編譯錯誤)

代表什麼:程式碼語法不正確,編譯器無法編譯。

常見原因

  • #include 遺漏:用了 vector 卻沒 #include <vector>
  • 語法錯誤:少了分號、括號不配對、關鍵字拼錯
  • 函式/型別名稱不存在:用了沒定義的變數或函式
  • 命名空間衝突:沒加 using namespace std; 就用 cout,或者變數名和標準函式庫衝撞

除錯方法

  1. 在自己的編譯器上編譯,看編譯訊息
  2. 仔細讀編譯錯誤訊息,它通常會指出第幾行
  3. 檢查所有 #include 是否完整
  4. 檢查 using namespace std; 是否存在(或改用完整名稱如 std::cout

CE Debug 手冊

編譯錯誤 可能原因 檢查項目
error: 'vector' is not a member of 'std' 沒有 #include <vector> 加上 #include <vector>
error: 'cout' was not declared 沒有 using namespace std; 或沒 #include <iostream> 加上兩行
error: expected ';' before '...' 語句後面少了分號 檢查該行末尾
error: request for member '...' in something not a struct 用了 . 來存取指標成員 改用 -> 或先解參考

TLE —— Time Limit Exceeded(超時)

代表什麼:程式編譯和執行都成功,但花的時間超過了題目規定的時間限制。

常見原因

  • 演算法複雜度太高O(n^3)O(2^n),當 n 很大時會超時
  • 無意中死迴圈:條件永遠不成立,迴圈一直跑
  • 重複計算太多次:沒有用記憶化或快取
  • IO 操作太多:逐個讀/寫,沒有優化

除錯方法

  1. 分析複雜度:算一下你的演算法大概是 O(n)O(n \log n) 還是 O(n^2)
  2. 估計執行次數:看題目限制(如 n \le 10^6),計算演算法最多要做多少次操作
    • 通常 1 秒內可以做 10^8 次簡單操作(加減乘除、賦值等)
    • 如果時間限制是 2 秒,可以做 2 \times 10^8
  3. 優化演算法:改用更快的演算法,或加上記憶化
  4. 優化 IO:改用 scanf/printf 或加上 ios::sync_with_stdio(false)

TLE 優化技巧

// 優化 IO(加在 main 開頭)
ios::sync_with_stdio(false);
cin.tie(nullptr);

// 或改用更快的 scanf/printf
int n;
scanf("%d", &n);
printf("%d\n", result);

MLE —— Memory Limit Exceeded(記憶體超限)

代表什麼:程式使用的記憶體超過了題目規定的上限。

常見原因

  • 陣列開太大int arr[10000000][10000000]; 一開就要 TB 級別記憶體
  • 無限遞迴或死迴圈建立變數:不斷分配新變數,不釋放舊的
  • 動態分配洩漏new 了卻沒 delete,導致記憶體不斷累積

除錯方法

  1. 計算陣列大小:一個 int 是 4 bytes,10^6 個就是 4 MB
    • 題目如果限制 64 MB,最多能開 16 \times 10^6int
    • 如果要開 2D 陣列,記憶體倍增,要很小心
  2. 改用動態分配:不是一次開整個陣列,而是邊讀邊存
  3. 優化資料結構:用更省記憶體的方式表示資料

MLE 優化技巧

// 不要這樣(會爆炸)
int dp[100000][100000];  // 4GB 記憶體!

// 改成動態分配
vector<vector<int>> dp(n, vector<int>(m));

// 或者如果只需要前一行的資訊,用滾動陣列
int prev[100000], curr[100000];

// 或改用更省的資料結構(如 map 只存非零值)