阶乘和数是各位数字阶乘之和等于自身的正整数,如1、2、145、40585;十进制下仅此四个,且最大不超过2540160。

什么是阶乘和数,它长什么样
阶乘和数(Factorion)是指一个正整数,其各位数字的阶乘之和恰好等于它本身。比如 145:1! + 4! + 5! = 1 + 24 + 120 = 145,所以它是阶乘和数。1 和 2 也满足(因为 1! = 1,2! = 2),而 40585 是目前已知最大的(在十进制下只有这四个:1, 2, 145, 40585)。
关键点在于:阶乘和数非常稀少,且有上界——因为对 d 位数来说,最大可能的阶乘和是 d × 9! = d × 362880,而最小的 d 位数是 10d−1。当 d ≥ 8 时,d × 362880 d−1,所以只需检查到 9999999(7 位)即可,实际更早就能截断。
预计算阶乘表避免重复调用 factorial()
每次拆位都要算阶乘,如果现场用递归或循环算 factorial(9),会大量重复——尤其在循环检查多个数时。直接预存 0! 到 9! 的值最稳:
int fact[10] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
注意:fact[0] = 1,别漏掉;数组大小必须是 10(索引 0~9);用 int 足够(9! = 362880,远小于 INT_MAX)。
常见错误:写成 fact[i] = i * fact[i-1] 但没初始化 fact[0],导致越界或未定义行为。
如何安全拆解数字并累加阶乘和
用取模和整除逐位提取数字,比转字符串快,也避免 std::to_string 开销和内存分配:
- 用
n % 10取末位,n / 10去末位,循环直到n == 0 - 每取一位
d,查表加fact[d],别直接调用函数 - 注意:原数要先保存,因为循环中
n会被清零;比较时用原始值
示例逻辑片段:
int original = n;
int sum = 0;
while (n > 0) {
int d = n % 10;
sum += fact[d];
n /= 10;
}
return sum == original;
别用 log10 或字符串遍历——慢,且引入浮点误差或额外依赖。
检查范围不能盲目从 1 到 INT_MAX
暴力枚举所有正整数毫无意义。已知数学结论:十进制阶乘和数只可能 ≤ 2540160(即 7 × 9!),因为 8 × 9! = 2903040 7 = 10000000,但实际验证发现最大是 40585,所以设上限为 50000 就够了。
实操建议:
- 循环从
1到50000(含),足够覆盖全部四个解 - 若想严格按理论上限,用
2540160,但耗时增加百倍以上,无必要 - 跳过
0:题目限定“正整数”,且 0! = 1,0 ≠ 1,不满足定义
容易被忽略的是:1 和 2 是合法解,但有人误以为阶乘和数必须 ≥ 3 位——不是,定义没这条限制。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











