1. 程式人生 > >題目28:大數階乘

題目28:大數階乘

題目連結:

描述

我們都知道如何計算一個數的階乘,可是,如果這個數很大呢,我們該如何去計算它並輸出它?

輸入

輸入一個整數m(0<m≤5000)

輸出

輸出每組測試資料中揹包內的物品的價值和,每次輸出佔一行。

樣例輸入

50

樣例輸出

30414093201713378043612608166064768844377641568960512000000000000

演算法思想:

可以使用一個數組來存放乘積的每一位數,最大5000的階乘,不超過2w位,故宣告陣列int a[20000]為存放乘積的每一位,且初始a[0] = 1,a[i] = {0} (i > 0)。
迴圈遍歷j從1遍歷到m,乘積的每一位a[i]都與j相乘,乘積為ans(ans = a[i] * j),故乘積的當前位為ans與進位數carray(初始值為0)和的個位數(即:a[i] = (ans + carray) % 10),當前進位數更新為carray = (ans + carray) / 10;以此類推。
比如:a[i]與j相乘結果ans = 5012,上次的進位carray = 3,故更新a[i] = (ans + carray) % 10 = (5012 + 3) % 10 = 5,更新carray為carray = (ans + carray) / 10 = (5012 + 3) / 10 = 501。

原始碼

#include <cstring>
#include <cstdio>
int a[20000];
int main()
{
    int m, ans, carray,num;//m為輸入數,ans為當前數與乘積數的每一位的乘積,carray為進位數
    //比如ans + carray = 5015,那麼更新乘積的當前位為5,carray更新為501(右移了一位),num為需要多少位陣列
    while (scanf("%d",&m)!=EOF)
    {
        memset(a,0,20000);
        a[0] = 1;
        carray = 0
; num = 1; for (int j = 1; j <= m; j++) { for (int i = 0; i < num; i++) { ans = a[i] * j; a[i] = (ans + carray) % 10; carray = (ans + carray) / 10; if (carray && num < i + 2) num = i + 2
; } } int i = 20000; while (!a[--i]); for (; i >= 0; i--) { printf("%d",a[i]); } printf("\n"); } return 0; }

最優原始碼


#include<stdio.h>
#include<string.h>
const int maxn=20000;
int a[maxn];
int main()
{
    int n,i,j,s,c;
    scanf("%d",&n);
    memset(a,0,sizeof(a));
    a[0]=1;
    for(i=2;i<=n;i++)
    {c=0;
    for(j=0;j<=maxn;j++)
    {
    s=a[j]*i+c;
    a[j]=s%10;
    c=s/10;
    }
    }
    for(j=maxn;j>=0;j--) if(a[j]) break;
    for(i=j;i>=0;i--) printf("%d",a[i]);
    printf("\n");
    return 0;
}