半素数是恰好由两个素数(可相同)相乘得到的正整数,如6=2×3、4=2×2;不能仅凭因数个数判断,因平方型半素数(如4、9)仅有3个因数,而合数如100虽有多个因数却非半素数,必须通过素因子分解验证其恰含两个素因子(计重)。

什么是半素数,以及为什么不能只看因数个数
半素数(semiprime)是指恰好能分解为两个素数乘积的正整数,比如 6 = 2 × 3、15 = 3 × 5、4 = 2 × 2(允许相同素数)。注意:12 = 2 × 2 × 3 不是半素数,因为它有三个素因子(计重);1、质数 也不是——前者无素因子,后者只有一个。
常见误区是用“正因数个数是否为 4”来判断:这在两个不同素数相乘时成立(如 6 的因数为 1,2,3,6),但对平方数型半素数(如 4、9、25)失效——4 的因数是 1,2,4,共 3 个。所以必须做素因子分解,而非数因数。
手写 is_semiprime 的核心逻辑
判断流程很直接:对 n 做试除,找出所有素因子(带重数),然后检查总个数是否恰好为 2。
实操建议:
- 先特判
n :直接返回 <code>false(最小半素数是4) - 从
2开始试除,直到i * i ;每次整除就记录一个素因子,并让 <code>n /= i - 循环结束后,若剩余
n > 1,说明它本身是个素因子(且大于 sqrt(original_n)),再记一次 - 最后检查素因子总数(含重复)是否等于
2
示例代码片段(不依赖外部库):
bool is_semiprime(int n) {
if (n 1) ++count;
return count == 2;
}
用 std::vector 存因子再验证的代价
有人会先把所有素因子存进 std::vector<int></int>,再检查 vec.size() == 2。这可行,但没必要——半素数最多只有 2 个素因子,一旦计数超过 2 就可提前返回 false,节省大量无效试除(比如对 60 = 2×2×3×5,第三个因子出来时就能终止)。
性能差异明显:对大合数(如接近 INT_MAX 的数),提前退出能把最坏复杂度从 O(√n) 降到接近 O(∛n)。尤其当输入含大量非半素数时,这个剪枝非常关键。
边界与易错点:1、质数、完全平方数
这几个值最容易被漏判或误判:
-
1:没有素因子 →count = 0→ 正确返回false - 质数(如
7):试除完剩自身 →count = 1→ 正确返回false - 平方数型半素数(如
49 = 7×7):循环中i=7整除两次 →count = 2→ 正确返回true - 注意
int溢出风险:计算i * i 时,若 <code>i接近sqrt(INT_MAX),i*i可能溢出。改用i 更安全
实际写的时候,别图省事跳过 n==1 或 n==质数 的测试用例——它们恰恰是暴露逻辑漏洞的高频点。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











