Semorphe

預備

進競賽之前要先知道的三件事。 · ⏱ 約 30 分鐘

你會學到三件事

  1. 溢位int 裝不下的時候不會報錯,會繞回去
  2. 複雜度:從「跑得完嗎」倒推「可以用什麼演算法」
  3. 短路&& 的右邊不一定會算

開始之前

⚠️ 右下角的目標選「C++ 競賽」。

從這裡開始,題目會告訴你「n ≤ 100000」這種話—— 而那句話直接決定你可以用什麼做法

一、溢位:安靜的錯

int a = 1000000;
cout << a * a << endl;      // 🔴 印出一個負數

int 大約裝到 21 億2³¹ - 1)。一兆放不進去。

而 C++ 不會報錯——它把多出來的位元丟掉,於是數字繞回去變成負的。

long long big = 1000000LL * 1000000LL;
cout << big << endl;        // 1000000000000  ✅

⚠️ 那個 LL 不能省。

long long big = 1000000 * 1000000;    // 🔴 還是錯的

因為右邊兩個都是 int乘法在變成 long long 之前就已經溢位了LL 是在說「這個字面值是 long long」。

型別 上限
int 約 2.1 × 10⁹
long long 約 9.2 × 10¹⁸

判準:算出來的中間值會不會超過 21 億? 會 → 全部用 long long。競賽裡多打幾個字比錯一題便宜。

二、複雜度:從時限倒推做法

比賽機器一秒大約跑 10⁸ 次基本運算。

n 的大小 可以用 不能用
n ≤ 20 指數(2ⁿ)
n ≤ 2000 O(n²) 雙層迴圈
n ≤ 10⁵ O(n log n) 排序、二分 O(n²) 會超時
n ≤ 10⁶ 只能 O(n) 或 O(n log n)

看到 n ≤ 100000 就知道雙層迴圈不能用。 這不是猜的——10⁵ × 10⁵ = 10¹⁰,是一秒能跑的一百倍。

題目給的範圍,就是它在告訴你要用哪一類演算法。

三、短路:右邊不一定會算

if (n > 0 && 10 / n > 1) cout << "safe" << endl;

n 是 0 的話,左邊 n > 0 不成立——右邊就不會算了

如果會算,10 / 0 會讓程式當掉。

什麼時候停
a && b a 不成立就停,不算 b
a || b a 成立就停,不算 b

⚠️ 所以順序有意義:把「檢查」放左邊,「會出事的操作」放右邊。

if (i < v.size() && v[i] == x)      // ✅ 先檢查範圍
if (v[i] == x && i < v.size())      // 🔴 反了,會越界

完成的樣子

int main() {
    long long big = 1000000LL * 1000000LL;
    cout << big << endl;
    int n = 5;
    if (n > 0 && 10 / n > 1) cout << "safe" << endl;
    return 0;
}

換你了

1000000LL 的兩個 LL 都拿掉,執行看看印出什麼。

(會是一個奇怪的數字——而沒有任何警告。)

這一課你做了什麼

如果卡住了

你看到 多半是因為
大數字變成負的 溢位。改用 long long
改了型別還是錯 字面值忘了加 LL——中間值先溢位了
明明檢查了還是越界 && 的順序反了
在編輯器打開這一課 →