题目链接:
http://acm.nyist.net/JudgeOnline/problem.php?pid=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;
}