CSU2020期中测试

关于CSU期中考试最后一题阶乘找零的一丢丢讨论:

题目描述
小帅接到一个任务,就是要找出一个整数n!中末尾到底有多少个0,请你帮帮他。
输入
多组样例,输入一个整数n(n≤10000)
输出
对于每一个输入的n,输出一个结果。每个输出占一行。
样例输入 Copy
5
16
27
样例输出 Copy
1
3
6
我首先看这道题,当然就按题目的思路一步步想,它让阶乘,我就阶乘,说啥干啥嘛,不过注意到整数n的范围是n<=10000,那当然直接求n的阶乘是相当不现实的,计算机是无法储存那么大的数
那么第一种方法明显就是解决大数的处理关于整型数据

int类型的数据储存大小是四个字节,储存的数据范围是-2,147,483,648 到2,147,483,647,unsigned int类型的数据在二进制中中的储存形式是没有符号位的,所以unsigned的数据范围是0到 4,294,967,295(2,147,483,647的2倍加1),即使是long long int 类型的数据是64位的(同理unsigned long long int类比unsigned int),也是远远不够算n的阶乘的,那当然要考虑的就是如何解决数据超限的过程。
要解决数据超限的问题,那当然想到的就是将阶乘的过程分开,一步一步做乘法,每次进行乘法后就想方设法化简数。

 int sum=0;
 int num=n;
        for(int i=n-1;i>=1;i--)
        {
            num=num*i;
            while(num%10==0&&num!=0)
            {
                sum++;
                num=num/10;
            }
            num=num%1000;
        }

这就是这道题的核心代码!!!!
核心要点:
    1.将阶乘的过程用for循环表示出来。
    2.在每次循环后记录末尾零的个数(当末尾出现零时,零乘以任何数均为零,所以末尾出现零,即不会改变)此时进行记录零的个数并消掉末尾零,消掉末尾的零并不会对以后末尾零的增加个数有任何影响。
    3.此时还要进行大数的化简 ,保证中间大数不会超过数据的储存范围,因为我要求的是末尾零的个数,而大数的首部对末尾零的个数不会有影响,所以我就选择了进行取余运算,取出末尾的部分就中了。当然不能只取最后一位,举个例子,4|25=100,而最后一位54=20,少了个零,所以大数的末尾若干位都对最后零的个数有影响,而n的取值范围为小于10000,即对10000取余是比较保险的选择,实际上我当时考试时对1000取余就通过了,对100取余AC40%,对10取余则只有可怜兮兮的AC%20啦。
      最后附上完整代码:

#include<stdio.h>
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int sum=0;
        int num=n;
        for(int i=n-1;i>=1;i--)
        {
            num=num*i;
            while(num%10==0&&num!=0)
            {
                sum++;
                num=num/10;
            }
            num=num%1000;
        }
        printf("%d\n",sum);

    }
    // getchar();getchar();
    return 0;
}

      此种写法应该说是简洁明了的处理大数的方法。c或c++处理大数的方法一般有两种,这道题用到的巧化简,还有就是用字符串。
<如果你觉得这道题用第一种方法理解有难度,不想考虑这么多超限的问题,那当然这道题还有第二种解决方法>
        第二种解决方法的思路即是看阶乘中的每个因数,将每个因数单独拿出看,每个因数即决定了末尾会出现多少个零
那么这个的关键就变成了单独研究每个数,而每个数的关键又是找5,当然找10和2也可,不过就增加了代码复杂度,我们力求代码的简洁明了易懂!!!!这点十分重要!!!!!

#include<stdio.h> 
int main(){
	int n;
	while(scanf("%d",&n)!=EOF){
		int ans=0;
		int j;
		for(int i=1;i<=n;i++)
		{
			j=i;
			while(j%5==0&&j!=0){
				ans++;
				j/=5;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

核心要点:
       确定每个阶乘的因数是5的多少倍,它是5的多少倍即决定了结果末尾会出现多少个零。
       这两种方法的代码都十分简洁明了,但第一种方法明显对技术水平要求更高,对知识的理解要求更高,而第二种方法则将此题当成一道数学题来写,对技术水平要求更低。对于这道题当然是首先意会哪种方法就用哪种了,都不难喽,哈哈哈哈如果各位靓仔们考试时卡在了那个点上,课后再揣摩一下吧哈哈哈哈哈哈
     关于大数的处理其实是恢常有学问的一件事啦,给自己挖个坑,以后还会更新有关大数处理相关的相关问题喽

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值