您的位置:首页 > 其它

The last non-zero digit in N![hdu-1066]

2010-09-28 16:27 316 查看
这道题被搁置了很久,又拿来做,终于搞懂了。

分析:

1.末尾的0是由2和5相乘产生的,而2的个数多于5的个数。

2.将5的倍数提取出来:令An为提取后的结果,函数f(x)表示x的最右非0位,N! = 5 * (floor(N/5)!) * An, f(N!) = f(floor(N/5)!)*f(5*An);

显然这是一个递归式,那么怎样求 f(5*An)?

易知,An中没有末尾0,则只需在An中提取出相应个数的2,即An除以相应个数的2。

处理出前100(A0 ~ A99 除以相应个数的2):

0: 1
1: 1
2: 2
3: 6
4: 4
5: 2
6: 2
7: 4
8: 2
9: 8
10: 4
11: 4
12: 8
13: 4
14: 6
15: 8
16: 8
17: 6
18: 8
19: 2
20: 6
21: 6
22: 2
23: 6
24: 4
25: 2
26: 2
27: 4
28: 2
29: 8
30: 4
31: 4
32: 8
33: 4
34: 6
35: 8
36: 8
37: 6
38: 8
39: 2
40: 6
41: 6
42: 2
43: 6
44: 4
45: 2
46: 2
47: 4
48: 2
49: 8
50: 4
51: 4
52: 8
53: 4
54: 6
55: 8
56: 8
57: 6
58: 8
59: 2


规律是很明显的。因为N可能很大,需要用大数除法计算N/5。

代码

#include <stdio.h>
#include <string.h>
#define MAXN 10000

char n[10000];

int lastdigit(char* buf)
{
const int mod[21]={6,6,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2,1};
int len=strlen(buf),a[MAXN],i,c,ret=1;
if(len==1) return mod[(buf[0]-'0')<=1?20:(buf[0]-'0')];
for (i=0;i<len;i++) a[i]=buf[len-1-i]-'0';
for (;len;len-=!a[len-1])
{
ret=ret*mod[a[1]%2*10+a[0]]%10;
for (c=0,i=len-1;i>=0;i--)
c=c*10+a[i],a[i]=c/5,c%=5;
}
return ret;
}

int main()
{
while(scanf("%s",n)!=EOF)
printf("%d\n",lastdigit(n));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: