一. 求N!末尾有几个0
因为影响生成0的是2和5的倍数,显然这些数的分解数含2的因子多于含5的因子,因此我们可以得出一个结论,N!的分解数中有多少个因子5,末尾就有多少个0,所以实际上就是去求N里面有多少个5。
采用层层剥皮法去求,先以5为步长,执行一次循环,求出含5的个数(个数为N/5取整),再求出含25的个数(因为一个数可以被5整除2次),有个问题还需要注意,25,125也是5的倍数,125也是25的倍数……一直到步长大于或等于N退出循环。
例求2016!后面0的个数呢?
同样按照上面的方法。
5的倍数个数为:
2016/5 = 403个
25的倍数个数为:
403/5 = 80个
125的倍数的个数为:
80/5 = 16个
625的倍数的个数为: 16/5 = 3个。
所以可以得出2016!后面0的个数为:403+80+16+3 = 502个.
代码如下
int ZeroTrail(int n)//计算n!的0的个数
{
int count = 0;
while(n)
{
count+=n/5;
n/=5;
}
return count;
}
二、近似整数
【题目描述】近似整数(Approximation.cpp/c/pas) POJ 1650给定一个浮点数A和一个整数L,求在范围[1,L]内的两个整数n和d,使得n/d能近似等于A,且使误差|A-n/d|最小。
【输入格式】第一行为一个浮点数A,第二行为一个整数L。
【输出格式】两个整数n和d。
【输入样例】3.1415926535897910000
【输出样例】355 113
算法分析:可以使用常规的二分法求解,也可以考虑追赶法求解。
追赶法:不断比较得出min(A-n/d),在n/d>A时d++,相反则n++,即d和n的追赶问题。
while(n <= L && d <= L)//在o~这个范围之内
{
cha = f - (double)n / d;//与浮点数进行比较
if (min > fabs(cha))//差值比min更小就更新
{
min = fabs(cha);
ansn = n;
ansd = d;
}
if (cha > 0)//后面小了,应当增大分子
n++;
else
d++;//否则减小分母
}
printf("%d %d
", ansn, ansd);