Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9118 | Accepted: 4795 |
Description
N N!
0 1
1 1
2 2
3 6
4 24
5 120
10 3628800
For this problem, you are to write a program that can compute the last non-zero digit of any factorial for (0 <= N <= 10000). For example, if your program is asked to compute the last nonzero digit of 5!, your program should produce "2" because 5! = 120, and 2 is the last nonzero digit of 120.
Input
Output
Sample Input
1
2
26
125
3125
9999
Sample Output
1 -> 1
2 -> 2
26 -> 4
125 -> 8
3125 -> 2
9999 -> 8
Source
算法描述:
方法一:
由于N!可能非常大,比如10000!形成的结果有35660位,远远超出我们正常long能够保存的数字范围,从而考虑用数组来存储大数的方法,定义一个short a[40000]的数组来存储结果的每一位,比如120,就可以用数组表示为a[0] = 1;a[1] = 2;a[3] = 0等,然后用一个方法来控制并完成计算,但这种方法太耗时间,还是另外采取别的方法比较好。缺点:超时
代码如下:
#include<stdio.h>
#include<string.h>
int a[40000];
int main()
{
int n,i,j,c,s;
while(~scanf("%d",&n))
{
memset(a,0,sizeof(a));
a[0]=1;
for(i=2; i<=n; i++)
{
s=0;
for(j=0; j<40000; j++)
{
c=a[j]*i+s;
a[j]=c%10;
s=c/10;
}
}
for(i=0;; i++)
if(a[i])
{
printf("%5d -> %d\n",n,a[i]);
break;
}
}
return 0;
}
方法二:
此方法体现了数学的技巧,我们对于一个数的阶乘,只关心最后末尾首次不是0的数字,对于高位的数字是多少或者N!具体等于多少并不关心,从而我们可以用/和%的方法对N!进行中途处理,当结果超过一定范围时,比如超过100000时,就对它进行%100000处理,从而把数的结果变小,而不影响最后5位的值;但是中途会出现末尾为0的情况,万一最后超过5个0怎么办?从而我们再用一个while循环来处理,比如5!=120,中途处理掉后,就成了12,不影响末尾数字的大小,比如12*6=72,而120*6=720,6!末尾首次不是0的数字为2,不影响结果,这就是算法的奥妙。我们总要想尽一切办法把和结果无关的过程处理掉,把相关的数字或者结果提取出来,达到我们想要的目的。
代码如下:
/***********************************************************************
Copyright (c) 2015,wangzp
All rights no reserved.
Name: 《Just the Facts》In PEKING UNIVERSITY ACM
ID: PROBLEM 1604
问题简述: 求一个整数N!(0<=N<=10000),然后把末尾首个不是零的数字输出出来。
算法描述:如果用数组存储大数字的方法,比较简单,但是容易超时。
由于题意中不是计算N!具体等于多少,而是要最末尾不是0的数字;
从而,我们对于高位的数字并不关心,所以我们可以在用%或者/来
控制数字的大小,对结果不会产生影响。
Date: Oct 10, 2015
***********************************************************************/
#include
int main(void)
{
int n,s,i;
while(scanf("%d",&n) == 1)
{
for(i = 1,s = 1; i <= n; i++)
{
s *= i;
while(s % 10 == 0)
{
s /= 10;
}
s = s % 100000;
}
printf("%5d -> %d\n",n,s % 10);
}
return 0;
}