23 阶乘最后的非0位
23 阶乘最后的非0位
作者:
问题描述 :
N的阶乘写作N!表示小于等于N的所有正整数的乘积。阶乘会很快的变大,如13!就必须用32位整数类型来存储,70!即使用浮点数也存不下了。你的任务是找到阶乘最后面的非零位。举个例子,5!=1*2*3*4*5=120所以5!的最后面的非零位是2,7!=1*2*3*4*5*6*7=5040,所以最后面的非零位是4。
输入说明 :
一个不大于1000的整数N。
输出说明 :
共一行,输出N!最后面的非零位。
输入范例 :
7
输出范例 :
4
解题思路:
阶乘的结果肯定会超出整数的范围(造成溢出),基于此我的第一个想法是建立一个数组rec[n],记录n阶乘的最后一位非0数x。
计算(n+1)阶乘最后一位非0数时,只需要将x*(n+1),然后提取最后一位非0数即可。
例如:
rec[2]=2
rec[3]=3*rec[2]=6;
看起来思路是对的,提交之后却无法AC。
一定是某种情况忘记考虑了,rec[0]=1应当初始化,但是这还不够。
通过Debug发现有种特殊情况,如:
12*15结果的最后一个非0位是8,但是如果按照之前的思路会是2*15=30,那么我会将rec数组中填入3,显然是错的。
问题出在哪里了呢?
正如12*15展现的那样,会丢失掉8,当你只记录上一次最后一个非0数时,就有可能丢失本次计算的进位与十位数的加和8。
基于此,我想到首先去掉每次运算的后缀0,然后要保留上一次运算的连续后x位非0数,x越大越好。例如保留上一次运算后5位的连续非0数如下:
for(i=1;i<=n;i++){ sum = sum*i; while(sum%10==0){ sum = sum/10; } sum = sum%100000; }
全部代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <math.h> 4 #include <string.h> 5 #include <ctype.h> 6 7 8 9 int answer(int n); 10 11 12 int main(){ 13 14 int n; 15 scanf("%d",&n); 16 printf("%d\n",answer(n)%10); 17 18 return 0; 19 } 20 21 int answer(int n){ 22 int sum = 1; 23 if(n==0){ 24 return sum; 25 }else{ 26 int i; 27 for(i=1;i<=n;i++){ 28 sum = sum*i; 29 while(sum%10==0){ 30 sum = sum/10; 31 } 32 sum = sum%100000; 33 } 34 } 35 return sum; 36 }