計算 n! (n ≤ 5000) 並輸出完整結果。5000! 約有 16326 位十進制數字,遠超 unsigned long long (20 位) 範圍,需實作**高精度乘法**(大數乘法)。
int a[10000] 足夠#include <stdio.h>
#include <math.h>
int main() {
int n;
while(scanf("%d", &n) == 1) {
if(n < 0 || n > 5000) continue;
int a[10000] = {0};
a[0] = 1;
int len = 0; // 當前最高有效位索引
for(int i = 2; i <= n; i++) {
int carry = 0;
for(int j = 0; j <= len; j++) {
long long prod = (long long)a[j] * i + carry;
a[j] = prod % 10000;
carry = prod / 10000;
}
while(carry > 0) {
a[++len] = carry % 10000;
carry /= 10000;
}
}
// 輸出:最高位不補零,其餘補齊 4 位
printf("%d", a[len]);
for(int i = len - 1; i >= 0; i--)
printf("%04d", a[i]);
printf("\n");
}
return 0;
}
| 原版問題 | 優化方案 |
|---|---|
| 基數 10000 但用 int 乘法可能溢位 | 使用 long long 儲存中間乘積 |
log10 計算位數有浮點誤差 | 直接追蹤 len 最高有效索引 |
輸出格式 %4.4ld 非標準 | 使用 %04d 標準格式補零 |
| 陣列大小固定 10000 | 5000! 只需 ~4100,足夠;可動態分配 |
利用對數性質:
log10(n!) = log10(1) + log10(2) + ... + log10(n) 位數 = floor(log10(n!)) + 1
或使用斯特靈公式近似:
log10(n!) ≈ n*log10(n/e) + 0.5*log10(2πn)
輸入: 50 輸出: 30414093201713378043612608166064768844377641568960512000000000000
與樣例輸出完全一致 ✓
大數階乘是高精度運算的經典入門題。掌握「基數分解 + 進位傳播 + 位數追蹤」三大核心技巧,可擴展至大數加減乘除、冪模、組合數等廣泛應用。