史密斯数是非质数且各位数字之和等于其所有质因数(含重复)各位数字之和的合数;判定需同时满足n>1、非质数、各位数字和等于质因数各位数字和。

什么是史密斯数?先看判定逻辑
史密斯数不是质数,但它的各位数字之和等于它所有质因数(含重复)的各位数字之和。比如 22:不是质数,各位和是 2+2=4;质因数分解为 2×11,质因数各位和是 2 + 1+1 = 4 → 满足条件,是史密斯数。
关键点有三个:非质数、各位数字和、质因数各位数字和。漏掉任意一个都会误判。
怎么高效算质因数各位数字和?别用 vector 存因数
直接边分解边累加各位数字,避免构造因数列表带来额外开销和内存:
int sumDigitsOfPrimeFactors(int n) {
int s = 0, temp = n;
for (int d = 2; d * d 1) s += sumDigits(temp); // 剩余的大于1的因子一定是质数
return s;
}
常见错误是把 temp == n 当作“没分解出因数”来判断质数——这是错的,比如 n=4,循环中 d=2 就能整除,根本不会走到最后。正确做法是单独调用 isPrime(n) 判断。
sumDigits 函数怎么写才不丢 0 或溢出?
别用字符串转换(开销大),也别用 log10 计算位数(浮点误差风险)。最稳的是循环取余:
int sumDigits(int x) {
int s = 0;
while (x) {
s += x % 10;
x /= 10;
}
return s;
}
注意:输入保证是正整数,不用处理负数或零;但若传入 10、100 这类含 0 的数,x % 10 会正确得到 0,累加无误。有人写成 while (x > 0) 也没问题,但 while (x) 更简洁且等价。
完整判定函数里最容易忽略的边界
史密斯数定义明确排除质数,所以必须显式检查:!isPrime(n)。但更隐蔽的坑是:
-
n == 1:不是质数,但也没有质因数 → 质因数各位和为 0,而 1 的各位和是 1 → 不等,不是史密斯数(正确) -
n == 4:质因数是 2×2,各位和 2+2=4,n 各位和也是 4 → 是史密斯数(常被手动验算漏掉) -
n是质数幂(如 8=2³):质因数各位和是 2+2+2=6,n 各位和是 8 → 不等,不是史密斯数
所以最终判定逻辑必须三段并列:
n > 1!isPrime(n)sumDigits(n) == sumDigitsOfPrimeFactors(n)
质数判断本身要处理 n == 2 和偶数快速返回,否则小数值下性能差异不大,但逻辑必须闭环。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











