給定 n,求 n! (階乘) 十進制表示中尾部連續 0 的個數。
邏輯:建立陣列 [1, 2, ..., n],反覆尋找因子 2 與 5 配對 (因為 10=2×5),計數配對次數。
// 概念碼,n>20 即溢位,n>10^5 記憶體/時間不可行
int count = 0;
int *arr = malloc(n * sizeof(int));
for (i=0;i
複雜度:O(n²) 時間、O(n) 空間。僅適合極小 n 驗證邏輯。
核心洞見:階乘中因子 2 的個數遠多於 5,**尾部零個數 = 因子 5 的總個數**。
每 5 個數貢獻 1 個 5,每 25 個數額外貢獻 1 個 (25=5²),每 125 個再額外 1 個...
公式:
zeros(n) = ⌊n/5⌋ + ⌊n/25⌋ + ⌊n/125⌋ + ... = Σ ⌊n/5ᵏ⌋
long long trailingZeros(long long n) {
long long count = 0;
for (long long p = 5; p <= n; p *= 5) {
count += n / p;
if (p > n / 5) break; // 防止 p*=5 溢位
}
return count;
}
| n | n! | 尾部零 | 公式計算 |
|---|---|---|---|
| 5 | 120 | 1 | 5/5=1 |
| 10 | 3628800 | 2 | 10/5=2 |
| 25 | ... | 6 | 25/5 + 25/25 = 5+1=6 |
| 100 | ... | 24 | 20+4=24 |
| 1000 | ... | 249 | 200+40+8+1=249 |
若求 n! 在 base B 下尾部零:
B = p₁ᵉ¹ × p₂ᵉ² × ... (質因數分解)。pᵢ,計算 n! 中 pᵢ 的指數 expᵢ = Σ ⌊n/pᵢᵏ⌋。min(⌊expᵢ / eᵢ⌋)。| 方法 | 時間 | 空間 | 最大可行 n |
|---|---|---|---|
| 暴力模擬 | O(n²) | O(n) | ~20 (溢位前) |
| 大整數乘法 + 計數 | O(n log n) | O(n log n) | ~10⁵ |
| 數學公式 (推薦) | O(log n) | O(1) | 10¹⁸+ (64位整數) |
核心思維:不要模擬過程,要分析本質。尾部零本質是質因數 2 與 5 的配對,而 2 過剩,故只需數 5。這種「質因數分解視角」是解決大數組合數學問題的萬能鑰匙。