史密斯数是非质数的合数,其各位数字之和等于其所有质因数(含重复)的各位数字之和;例如22=2×11,数字和均为4,故为史密斯数。

什么是史密斯数?先看判定逻辑
史密斯数不是质数,但它的各位数字之和等于它所有质因数(含重复)的各位数字之和。比如 22:
- 非质数 ✓
- 数字和:
2 + 2 = 4 - 质因数分解:
2 × 11→ 数字和:2 + 1 + 1 = 4
→ 所以 22 是史密斯数。
关键点在于:必须先排除质数(质数不算),再算两组数字和是否相等。别跳过质数判断,否则 13 这种会被误判。
怎么写质因数分解函数?注意重复因子
质因数分解不能只返回不重复的因子(如用 set),必须保留重复次数,因为数字和依赖每个质因数的每一位。
- 从小到大试除,从
2开始,直到i * i <= n - 每次整除就累加该因子的各位数字和,不存因子本身更省事
- 最后若
n > 1,说明剩下一个质因数,也要加它的数字和
int sumOfDigits(int n) {
int s = 0;
while (n) { s += n % 10; n /= 10; }
return s;
}
<p>int primeFactorDigitSum(int n) {
int s = 0;
for (int i = 2; i * i <= n; i++) {
while (n % i == 0) {
s += sumOfDigits(i);
n /= i;
}
}
if (n > 1) s += sumOfDigits(n);
return s;
}</p>如何避免常见误判?三个易错点
-
1 不是史密斯数(既非质数也无质因数,数字和为 1,但质因数数字和为 0)
-
4 是史密斯数(4 = 2×2,数字和 4,质因数数字和 2+2=4)
- 别漏掉合数判断:直接调
is_prime(),返回 false 才继续;否则像 17 这种质数会进后续计算,导致错误
1 不是史密斯数(既非质数也无质因数,数字和为 1,但质因数数字和为 0) 4 是史密斯数(4 = 2×2,数字和 4,质因数数字和 2+2=4) is_prime(),返回 false 才继续;否则像 17 这种质数会进后续计算,导致错误 合数检查建议写成:
bool is_composite(int n) {
if (n < 4) return false; // 1,2,3 都不是合数
if (n % 2 == 0) return n != 2;
for (int i = 3; i * i <= n; i += 2)
if (n % i == 0) return true;
return false;
}
完整判断函数怎么组织?顺序不能乱
先验条件必须按顺序检查,否则逻辑短路或越界:
立即学习“C++免费学习笔记(深入)”;
-
n <= 1→ 直接false -
!is_composite(n)→ 排除非合数(即质数或 1) - 计算原数数字和
sumOfDigits(n) - 计算质因数数字和
primeFactorDigitSum(n) - 两者相等才返回
true
注意 primeFactorDigitSum() 内部修改了 n 的副本,不影响外层;但如果你传入的是引用或全局变量,就会出问题 —— 始终用值传递。
实际用的时候,边界值如 4、22、27(3×3×3 → 2+7=9,3+3+3=9)可以快速验证逻辑是否稳。质因数分解那步最容易少加最后剩下的大质数,一丢就全错。


















