LintCode 第二题 坑爹的尾部的零

本文探讨了计算n阶乘尾部零的个数的问题,通过分析与优化,最终得出仅需关注5的倍数及其幂次即可快速计算出结果。

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

设计一个算法,计算出n阶乘中尾部零的个数

样例

11! = 39916800,因此应该返回 2。

起初认为是个很简单的题 后来发现 给的代码区域是这样的。


是的 你没看错 就是long long  所以存起来阶乘得数sum*= 是不可能的。

下意识的  想到了只存最后一个数

#include<iostream>
using namespace std;
long long trailingZeros(long long n) {
       		int flag=0; int a=1,b=5;
	   for(long long i=1;i<=n;i++)
       	{
       		if((a*(i%10))%10==0)
       			{
       				
       				/*if(i%5==0)
       					{
       						while(i%b==0)
       							{
       								flag++;
       								b=b*b;
       							}
       						b=5;
       					continue;
       					}*/
       					flag++;
       				if(i%10!=0)a=(a*(i%10))/10%10;
       					else 
       						{       
							   		a=i;							
       							while(a%10==0)
       								{
       									a=a/10;
       								}
       								a=a%10;
       								//acout<<i<<"*"<<a<<" ";
       						}
       			}
       		else 
       			{
       				a=(a*(i%10))%10;
       			}
       		cout<<i<<"*a="<<a<<"flag="<<flag<<endl;
       	}
       return flag;
    }
int main()
{
	long long a;
	cin>>a;
	cout<<trailingZeros(a);
	return 0;
}
测试输出如下 a存的是每次循环乘积的个位数 flag是0的个数

两个问题 或者是两个发现:
1. 可以发现i每逢5 flag就多一个
2.flag 在25的时候少了一个  也就是说  25的时候  会出现两个0。(检验后发现的 25的时候正确答案应该是6)

也就是说  0的个数与i的5^n有关系.

深究其原因  我们发现  每一次循环 之后a=5 才有可能与i+1的个位数乘出来一个“0”,而与5相乘的i+1,要么是6,要么是10的倍数 也就是自带一个整数,所以逢5必有0.

而所有25的倍数可以拆分成两个0 125的倍数可以拆分成3个0.
所以在i循环到5的时候做一个判断
#include<iostream>
using namespace std;
long long trailingZeros(long long n) {
       		int flag=0; int a=1,b=5;
	   for(long long i=1;i<=n;i++)
       	{
       		if((a*(i%10))%10==0)
       			{
       				
       				if(i%5==0)
       					{
       						while(i%b==0)
       							{
       								flag++;
       								b=b*b;
       							}
       						b=5;
       					continue;
       					}
       					flag++;
       				if(i%10!=0)a=(a*(i%10))/10%10;
       					else 
       						{       
							   		a=i;							
       							while(a%10==0)
       								{
       									a=a/10;
       								}
       								a=a%10;
       								//acout<<i<<"*"<<a<<" ";
       						}
       			}
       		else 
       			{
       				a=(a*(i%10))%10;
       			}
       		cout<<i<<"*a="<<a<<"flag="<<flag<<endl;
       	}
       return flag;
    }
int main()
{
	long long a;
	cin>>a;
	cout<<trailingZeros(a);
	return 0;
}
答案虽然没问题 但是思来想去 还是做了许多冗余操作:
    既然阶乘数只与5有关  为何我不直接越过数本身 判断n包含5的个数呢。
最终代码:
    
class Solution {
public:
    /*
     * @param n: A long integer
     * @return: An integer, denote the number of trailing zeros in n!
     */
    long long trailingZeros(long long n) {
        	// write your code here
        long long count = 0;
        long long temp=n/5;
        while (temp!=0) {
            count+=temp;
            temp/=5;
        }
        return count;
    }
};
成了~!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值