解题思路:
末尾的0都是由2和5相乘得到的,举几个例子:
40=2^3*5^1 只有一个5和2对应,所以只有一个0
500=2^2*5^3 只有两个2和5对应,所以只有两个0
也就是说,末尾的0的个数就是2和5指数中最小的指数
我们只需要进行质因数分解就可以了,很容易知道,在阶乘里面2出现的次数是远大于5的,所以只需要找到5出现的次数就可以了。
需要注意的是,这道题不是n的阶乘是1-n的阶乘,需要两次循环,外重循环1-n,内循环表示i的阶乘,这样时间复杂度是很大的。
所以有了这样一个式子:z+=(n-i+1)*k;
举例 n=7 s=1!*2!*3!*4!*5!*6!*7!
在5!的时候k=1,那么后面的6! 7!也会有一个5,所以最后是3个5 末尾3个0
参考代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define ll long long int main(){ ll i; ll n,m=0,k=0,z=0; scanf("%lld",&n); for(i=1;i<=n;i++){ m=i; k=0; while(m%5==0){ k++; m/=5; } z+=(n-i+1)*k; } printf("%lld",z); return 0; }
对应这道题的还有二进制末尾0的问题,不过我在dotcpp上没有找到类似问题,就在这里写一下当扩展吧。
二进制末尾0我们可以用右移判断最低位是否为1来进行,例如:
12(1100)=2^2*3,末尾有两个零。
14(1110)=2^1*7,末尾有一个零。
如果一个数的二进制最低位为1的话,他一定是一个奇数,奇数的因子里面一定没有2,所以做右移除2就相当于把一个数的因子2全部找出来,最后让这个数成为一个奇数。
所以二进制末尾0个数==因子2的个数。
这样时间复杂度为log n,不过一般这样的问题都是很多数相乘问题,最后的答案不能用变量表达出来。
所以我们只需要对输入的数进行分解,找到所有因子2的次数,就是答案了。
0.0分
2 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复