n的阶乘末尾零的个数

来源:互联网 发布:彩票过滤软件 编辑:程序博客网 时间:2024/04/28 10:43

n的末尾的零的个数,对于这个问题我们首先可以想到末尾零是怎么来的,很明显,它是由因式中的2*5构成的,n的阶乘的因式中有多个2*5,那么n!末尾就有多少个零,那么问题就变成了求n!中有多少个2*5了,又由于因子2出现的频率要远远大于5出现的频率,进而问题简化成了其n!的因式分解中5的幂数。这里有两种方法,一种O(n^2)的和一种O(log n)的:

先来看一下O(n^2)的吧,这种比较容易理解

这种方法呢就是枚举每一个不大于n的数中5的倍数,然后对每一个倍数进行分解,看里面有多少个5,再把这些倍数分解下的5的个数相加,因为是二重循环,故复杂度高一些,时间上会超出一些题目的时间限制。

代码如下:

#include <cstdio>using namespace std;int solve(int n){    int num=0;    for(int i=5;i<=n;i+=5)    {        int j=i;        while(j%5==0)        {            num++;            j/=5;        }    }    return num;}int main(){    int n;    while(scanf("%d",&n)!=-1)      printf("%d\n",solve(n));    return 0;}


另一只O(log n)的算法其实是数论中的东西。

我们知道,对于一个数m,我们要找出不大于m的数中有多少个是5的倍数,那么只需拿m/5即可,商即为5的倍数的数目,所以对于n!来说,我们拿n/5,那么得到的结果就是这n个数中能直接分解出的因子5的个数,但不要忘了,这是直接分解出的因子5,此外,一个数的因子还可能含有25,75,125等等这样的数,同理,我们拿n/25,那么就等得到这n个数中能直接分解出的因子25的个数,每次乘5,乘到大于n结束,把这些因子倍数的数目加起来即为n!中一个可以分解出的5的数目,也就是n!末尾零的数目。

代码如下:

#include <cstdio>using namespace std;int solve(int n){    int num=0;    int t=1;    while(t<=n)    {        t*=5;        num+=n/t;    }    return num;}int main(){    int n;    while(scanf("%d",&n)!=-1)      printf("%d\n",solve(n));    return 0;}


 

题目有POJ1401    ZOJ2202

0 0
原创粉丝点击