語法書 / AA 競程語法書 下冊 / 第十五單元 / 手造測資:從極端情況下手

15.6 手造測資:從極端情況下手

15.1 的流程走到「尋找會錯的測資」時,範例測資常常幫不上忙——因為你的程式已經過了範例。下一步就是自己造。造測資不是亂槍打鳥,有一份固定的靈感清單:極端情況(edge cases)。錯誤特別喜歡躲在範圍的邊邊角角。

極端測資清單

造什麼 特別會抓到的錯
n = 1(最小規模) 「至少要有兩個元素」的隱藏假設、迴圈少跑或多跑一圈
n = 0(若題目允許) 空輸入的處理、除以 0
最大範圍(n 與數值都塞到上限) 整數溢位、陣列開太小、TLE
全部相同 「嚴格大於」與「大於等於」搞混、找第二大這類題的重複值處理
已排序/倒序 排序相關邏輯、「第一個」「最後一個」的方向錯誤
負數與 0(若範圍允許) 「想當然的正數假設」——15.1mn = 0 正是被全正數測資抓到的
剛好踩在邊界值(恰等於上限或下限) <<= 的差一錯誤

用法:對照題目的輸入範圍,把清單裡題目允許的項目逐一造出來餵程式,每一組都先手算好正確答案再比對。範圍寫 1 \le n 就不用造 n = 0——但 n = 1 一定要造,它是合法的!

大測資用程式造,寫進檔案

清單裡的「最大範圍」有 10^5 個數字,手打會先陣亡——讓程式代勞,直接用 14.3ofstream 寫進檔案:

#include <bits/stdc++.h>
using namespace std;

int main() {
    ofstream fout("big.txt");           // 把測資寫進檔案
    int n = 100000;                     // 題目給的最大範圍
    fout << n << '\n';
    for (int i = 0; i < n; i++) {
        fout << 1000000000 << ' ';      // 全部塞上限值:順便逼出溢位
    }
    fout << '\n';
    return 0;
}

跑完得到一個 big.txt(開頭是 100000,第二行是十萬個 10^9,本站實測產出約 1.1 MB)。接著用 14.7 的重導向把它餵給你的解答:

./a.out < big.txt

一石三鳥:答案對不對(極大值會不會溢位)、跑得快不快(拿手機計時,遠超時限就是 TLE 預定)、會不會當掉(陣列夠不夠大)。想在程式內開檔也可以,14.4freopen 加一行即可。

動手試試看:拿 15.1 的「最大值減最小值」錯誤程式當靶子,把清單裡的每一項各造一組測資餵它,記錄哪幾項能抓到 mn = 0 的 bug(提示:至少有兩項抓得到)。這個練習會讓你對「哪種錯躲在哪種邊界」長出直覺。