阶乘末尾零的个数由因子5的总数决定,因因子2恒多于5;需累加n÷5、n÷25、n÷125…直至除数超过n,时间复杂度O(log₅n)。

为什么阶乘末尾的零只由因子5决定
阶乘末尾的零来自 10 = 2 × 5,而阶乘中因子2的数量永远多于因子5(比如每两个数就有一个偶数),所以真正限制零的个数的是因子5的总数量。注意:像 25、125 这样的数会贡献多个5(25 = 5² 贡献两个,125 = 5³ 贡献三个),不能只除一次。
用循环累加 n / 5、n / 25、n / 125…
这是最常用且高效的做法,时间复杂度 O(log₅ n),不涉及大数运算,也无需计算完整阶乘(对大 n 来说根本不可行)。
实操要点:
- 初始化计数器为 0
- 用变量
powerOf5 = 5,每次循环后乘以 5 - 只要
powerOf5 ,就将 <code>n / powerOf5(整除)加到计数器中 - 整除是关键:C++ 中
int除法天然截断,不用额外取整
int trailingZeroes(int n) {
int count = 0;
for (long long p = 5; p <= n; p *= 5) {
count += n / p;
}
return count;
}
容易踩的坑:int 溢出和边界值
p *= 5 在循环中可能溢出——比如 n 接近 INT_MAX 时,p 下一次乘5前还是合法的,乘完就变成负数,导致循环失控。所以必须用 long long 存 p(哪怕 n 是 int)。
立即学习“C++免费学习笔记(深入)”;
其他常见问题:
-
n = 0或n = 1时结果是 0,代码自然覆盖,无需特判 - 别写成
while (n > 0) { count += n / 5; n /= 5; }—— 这虽然等价,但修改了原参数,语义不清,还可能误导人以为在“分解 n” - 不要尝试用
std::factorial(n)(C++ 标准库根本没有这个函数)
如果真要验证小数字,可以手算对比
例如 n = 25:
-
25 / 5 = 5(5,10,15,20,25 各一个5) -
25 / 25 = 1(25 额外再贡献一个5) - 总计 6 个零 →
25! = 15511210043330985984000000,末尾确实 6 个零
超过 n ≈ 20 就别手动算阶乘了,数值增长太快,重点始终是统计因子5的个数——这才是本质,不是“算阶乘再数零”。


















