23 阶乘最后的非0位

23 阶乘最后的非0位

作者: XXX时间限制: 1S章节: 循环

问题描述 :

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 }

 

posted @ 2020-03-17 13:43  focusDing  阅读(637)  评论(0编辑  收藏  举报