在一個 A×B 的矩形網格中,共能找到多少個子矩形?這是一個經典的組合數學問題,也是 C 語言初學者常遇到的練習題。輸入多組測試數據(不超過 10000 組),每組包含兩個整數 A、B(1 ≤ A,B ≤ 1000),程序需輸出對應的矩形總數,直到 EOF 結束。
初學者往往習慣用固定大小的數組存儲所有輸入,並以 0 作為結束標記:
long int A[1000], B[1000];
for(i=0; i<1000; i++) {
scanf("%d", &A[i]);
if (A[i]==0) break;
scanf("%d", &B[i]);
}
缺點:題目要求處理到 EOF,而非遇 0 結束;數組大小固定,若測試數據超過 1000 組會溢出;函數聲明放在 main 內部,不符合最佳實踐。
修正後使用 while(scanf("%d%d", &A, &B) != EOF),但初學者以為 EOF 是鍵盤輸入的 "eof" 三個字符,導致程序無法正常結束。
關鍵知識點:EOF 是 stdio.h 中定義的宏(通常為 -1),表示輸入流結束。Windows 控制台中按 Ctrl+Z(行首),Linux/Mac 按 Ctrl+D 才能產生 EOF。
temp 變量,直接累加long int,配合 %d 格式符構成類型不匹配,雖然在某些平台上長度相同而僥倖通過,但屬於未定義行為採用組合數學公式:在 A×B 網格中,選兩條垂直線、兩條水平線即可確定一個矩形,總數為 C(A+1,2) * C(B+1,2) = A*(A+1)/2 * B*(B+1)/2。時間複雜度 O(1),避免多重循環。
#include <stdio.h>
long long count_rectangles(int a, int b) {
return 1LL * a * (a + 1) / 2 * b * (b + 1) / 2;
}
int main(void) {
int A, B;
while (scanf("%d %d", &A, &B) == 2) {
printf("%lld\n", count_rectangles(A, B));
}
return 0;
}
while (scanf("%d %d", &A, &B) == 2) 比判斷 EOF 更直觀int 配 %d,long long 配 %lld)這個案例生動展示了從「能跑通」到「正確、高效、可維護」的代碼進化過程,是初學者從語法掌握走向工程思維的縮影。