1. 程式人生 > >JSK-217 階乘【大數】

JSK-217 階乘【大數】

階乘 n的階乘定義為n!=123*……*n 如3!=6 n!通常最後會有很多0,如5!=120 最後有一個0,現在統計n!去除末尾的0後,最後k位是多少 輸入格式: 第一行包括兩個數n,k 輸出格式: 如果n!不止k位,則輸出最後k位,如果不足k位,則將剩下的全部輸出 7!為5040,去除末尾的0為504,最後兩位為04 100%滿足1< =n< =20 1< =k< =9 樣例輸入 7 2 樣例輸出 04

問題連結JSK-217 階乘 問題描述:(略) 問題分析:     階乘計算會越算越大,然而只需要計算最後k<=9位就好辦了,使用模除可以取出最後若干位來。     需要分析一下,末尾的0是怎麼來的。一般而言,有兩種產生末尾0的原因:一是乘以末尾為0的數,即10的倍數的數;二是含有因子2的數與含有因子5的數的乘積(10=2*5)得到的,而含有因子2的數遠多餘含有5因子數。     計算過程中,如果僅僅取最右邊k位持續計算則會造成有效數字的丟失,所以先多取一些位進行計算。最後再用模除取出最後k位。 程式說明

:     程式中,輸出k位前置為0的數的做法略微與眾不同,值得效仿。用迴圈處理來實現高位補0那是浮雲。 參考連結:(略) 題記:格式字串也是可以在程式中算出來的。

AC的C語言程式如下:

/* JSK-217 階乘 */

#include <stdio.h>

typedef long long LL;

#define BASE 10
#define MOD 1000000000000000LL

int main(void)
{
    int n, k, i;
    LL mod, ans;

    scanf("%d%d", &n, &k);

    mod = 1;
    for(i = 1; i <= k; i++)
        mod *= BASE;

    ans = 1;
    for(i = 2; i <= n; i++) {
        if(i % BASE == 0)
            continue;

        ans *= i;
        while(ans % BASE == 0)
            ans /= BASE;

        ans %= MOD;
    }
    and %= mod;

    // 輸出結果
    char fmt[10];
    sprintf(fmt, "%%0%dlld\n", k);
    printf(fmt, ans);

    return 0;
}