題目28:大數階乘
阿新 • • 發佈:2019-01-31
題目連結:
描述
我們都知道如何計算一個數的階乘,可是,如果這個數很大呢,我們該如何去計算它並輸出它?
輸入
輸入一個整數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;
}