面试题:计算n!中结尾零的个数

本文介绍了一种计算阶乘结尾连续零数量的高效算法,并通过C语言实现该算法。核心思路在于统计阶乘分解后的5的个数,因为2的数量总是多于5,故5的个数决定了零的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/************************************************************
算法思想:在1-10两个数相乘要产生0,只有 10×1=2×5,2×5。
200!=200×199×198……×2×1=2×5×2×5×2×199…. ×2×1;可以分解为质数相乘的形式,
很明显有2的个数比5的多,所以只要求出200的阶乘可分解出多少个5相乘,
就可得到200的阶乘结尾的连续的零的个数.
即:num=[200/5]+[200/5/5]+[200/5/5/5].
注: [x]表示对x取整.
所以可以通过这个思路很容易的得到任意阶乘结尾连续的零,其示例C语言代码如下:
*************************************************************/
#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
using namespace std;
#define MAX 100
//MAX 是计算结果的最大位数 取为100位
void factorial(int n,char output[])
{
    int i, j, cin, tmp;
    int result[MAX];
    memset(result, 0, sizeof(result)); //初始化为0
    result[0] = 1;
    for(i = 2; i <= n; ++i)  //从2 开始计算阶乘
    {
        cin = 0; //进位初始化为0
        for(j = 0; j < MAX; ++j)
        {
            tmp = result[j] * i + cin; //cin进位
            result[j] = tmp % 10;
            cin = tmp / 10;
        }
    }
    for(i = MAX - 1; i >= 0; --i) //忽略前导的0
        if(result[i]) break;
    for(j = i; j >= 0; j--)   //将结果倒叙打印在结果数组中
    sprintf(output++,"%d", result[j]);
    //注意sprintf的第一个参数是char型指针
}
/*计算n!结尾零的个数,返回结尾零的个数。*/
int GetZeroNum(int n)
{
    int num=0;//n!结尾零的个数
    int b=1;//5的次方
    while(1)
    {
        b*=5;
        num+=n/b;
        if(b>n)
        break;
    }
    return num;//返回结尾零的个数
}
int  main()
{   char out[MAX]={0};
    int i=5;
    factorial(i,out);
    cout<<"factorial("<<i<<") is "<<out<<endl;
    cout<<"factorial("<<i<<") the number of 0 in the rear is "<<GetZeroNum(i)<<endl;


    i=10;
    factorial(i,out);
    cout<<"factorial("<<i<<") is "<<out<<endl;
    cout<<"factorial("<<i<<") the number of 0 in the rear is "<<GetZeroNum(i)<<endl;


    i=20;
    factorial(i,out);
    cout<<"factorial("<<i<<") is "<<out<<endl;
    cout<<"factorial("<<i<<") the number of 0 in the rear is "<<GetZeroNum(i)<<endl;


    i=30;
    factorial(i,out);
    cout<<"factorial("<<i<<") is "<<out<<endl;
    cout<<"factorial("<<i<<") the number of 0 in the rear is "<<GetZeroNum(i)<<endl;
}
/********************************
factorial(5) is 120
factorial(5) the number of 0 in the rear is 1
factorial(10) is 3628800
factorial(10) the number of 0 in the rear is 2
factorial(20) is 2432902008176640000
factorial(20) the number of 0 in the rear is 4
factorial(30) is 265252859812191058636308480000000
factorial(30) the number of 0 in the rear is 7


Process returned 0 (0x0)   execution time : 0.109 s
Press any key to continue.


********************************/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值