首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

POJ 1423 Big Number:階乘位數的兩種高效計算法

     編輯:C++ 入門

題目

給定整數 m (1 ≤ m ≤ 10^7),求 m! 的十進制位數。多測試用例,首行給出測試數 n。

數學基礎

log10(m!) = log10(1) + log10(2) + ... + log10(m),位數 = floor(log10(m!)) + 1。

方法一:預計算前綴和 (空間換時間)

預先計算 a[i] = a[i-1] + log10(i) 至足夠大的 N (如 8,000,000)。查詢時:

  • m < N:直接 floor(a[m]) + 1
  • m ≥ N:a[N-1] + Σ_{i=N}^m log10(i) 現算補上
#define N 8000000
double a[N];
void init() {
    a[0] = 0;
    for (int i = 1; i < N; ++i) a[i] = a[i-1] + log10(i);
}
int main() {
    init();
    int T, m; scanf("%d", &T);
    while (T--) {
        scanf("%d", &m);
        if (m < N) printf("%d\n", (int)a[m] + 1);
        else {
            double s = a[N-1];
            for (int i = N; i <= m; ++i) s += log10(i);
            printf("%d\n", (int)ceil(s));
        }
    }
}

方法二:斯特靈公式近似 (O(1) 查詢)

n! ≈ √(2πn) (n/e)^n,取對數:

log10(n!) ≈ 0.5*log10(2πn) + n*log10(n/e)

忽略高階小項,直接計算並取 ceil。特判 n=1 為 1 位。

int main() {
    const double pi = acos(-1), e = exp(1);
    int T, n; scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        double s = 0.5*log10(2*pi*n) + n*log10(n/e);
        if (n == 1) s = 1;
        printf("%d\n", (int)ceil(s));
    }
}

比較與選擇

方法時間空間精度
前綴和O(1) 查詢 (預處理 O(N))O(N) ≈ 64 MB精確
斯特靈O(1) 無預處理O(1)極高 (10^7 內誤差 < 1)

競賽中通常採用斯特靈公式,代碼極短且無記憶體壓力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved