題目鏈接:POJ 2084
核心洞察:圓周上 2n 個點兩兩連線且線段不相交的方案數,即為第 n 個卡特蘭數(Catalan Number)。
定義 h(n) 為 2n 個點合法連線方案數:
h(0) = 1(空集視為 1 種方案)h(1) = 1(2 個點僅 1 條連線)h(n) = Σ h(i) * h(n-1-i),其中 i = 0..n-1,n ≥ 2等價閉形式:h(n) = C(2n, n) / (n+1) = (2n)! / (n! * (n+1)!)
前幾項:1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862... 增長極快,n=200 時已超過 10115,必須用大整數。
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 1. 預計算 h[0..200]
BigInteger[] h = new BigInteger[201];
h[0] = h[1] = BigInteger.ONE;
for (int n = 2; n <= 200; n++) {
h[n] = BigInteger.ZERO;
for (int i = 0; i < n; i++) {
h[n] = h[n].add(h[i].multiply(h[n - 1 - i]));
}
}
// 2. 讀入多組測試用例,-1 結束
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int n = in.nextInt();
if (n == -1) break;
System.out.println(h[n]);
}
}
}
| 技術點 | 說明 |
|---|---|
| BigInteger | Java 內置任意精度整數,支援加減乘除,完美應對超長整數 |
| 打表預計算 | 測試用例可能多次查詢同一 n,O(n²) 預計算後 O(1) 回答,總耗時 ~172ms(POJ 環境) |
| 遞推順序 | 外層 n 從 2 到 200,內層 i 從 0 到 n-1,保證 h[i] 和 h[n-1-i] 已計算 |
| 輸入結束條件 | 讀到 -1 終止,符合 POJ 題目要求 |
h(n) = h(n-1) * (4n-2) / (n+1) 可降為 O(n) 預計算,但需精確整除,BigInteger 除法較慢,實測遞推更快System.out.println(h[n]),BigInteger 默認十進制無前導零,符合要求輸入:
1
2
3
-1
輸出:
1
2
5
與卡特蘭數序列完全吻合。
此題是「識別模型 → 寫出遞推 → 大整數實現 → 打表優化」的經典練習,適合鞏固組合數學與 Java 高精度計算基本功。