半素数是恰好由两个素数(可相同)相乘得到的正整数,即其质因数分解中素因子个数(计重)恰为2;试除到√n足够,因若n=p×q且p≤q,则必有p≤√n,故不会漏判。

什么是半素数,以及为什么不能只试除到√n
半素数是指恰好由两个素数相乘得到的正整数(两个素数可以相同,比如 4 = 2 × 2、9 = 3 × 3、6 = 2 × 3 都算;但 8 = 2 × 2 × 2 不算,12 = 2 × 2 × 3 也不算)。关键在于:**因子分解后,素因子的总个数(计重)必须恰好为 2**。
常见误区是认为“只要能被某个素数整除一次,再看商是不是素数就行”——这在 n 很大时可能漏判,比如 n = 97 × 101(两个大素数),你若只试除到 sqrt(n) ≈ 99,会找到 97,然后检查 n / 97 == 101 是否为素数,没问题;但如果 n = p × q 且 p ,你仍能靠这个逻辑捕获;真正危险的是 <code>n 本身是素数(此时只有 1 个素因子)或有 ≥3 个素因子(比如 p × q × r),但试除过程可能提前误判为“两因子”。所以核心不是“找不找得到”,而是“能不能确认只有两个”。
用试除法判断半素数的可靠步骤
对给定正整数 n,需完整做三件事:
- 若
n ,直接返回 <code>false(最小半素数是 4) - 遍历
i从 2 到sqrt(n)(含),找出第一个能整除n的i - 若没找到任何因子 →
n是素数 → 不是半素数 → 返回false - 若找到第一个因子
i,则令q = n / i;此时必须同时满足:i是素数、q是素数、且i ≤ q(避免重复,但非必需) - 特别注意:如果
i找到了,但q还能被更小的素数整除(比如n = 12,i = 2,q = 6,而 6 = 2 × 3 → 实际有 3 个素因子),那说明n不是半素数。因此不能只检查q是否为素数,还要确保它不能再被 ≤sqrt(q)的素数整除 —— 但更简单做法是:**只要i是最小素因子,那么q必须是素数,否则n至少有三个素因子**
所以实操中,只需:
- 写一个辅助函数
is_prime(x),处理x 、<code>x == 2、偶数、奇数试除到sqrt(x) - 主函数中,从
i = 2开始试除;一旦n % i == 0,立刻检查is_prime(i)和is_prime(n / i);若都为真,返回true;否则返回false - 如果循环结束都没整除 →
n是素数 → 返回false
示例:n = 15 → i = 3 整除 → is_prime(3) == true, is_prime(5) == true → 返回 true。n = 16 → i = 2 整除 → is_prime(2) == true, is_prime(8) == false → 返回 false。
边界与性能要注意的几个点
半素数判定看似简单,但在实际编码中容易栽在这些地方:
-
n = 1、0、负数:按定义,半素数是正整数,且 ≥4,所以开头加if (n -
sqrt(n)计算要用整型截断,比如(int)sqrt(n)或更稳妥地用i * i 避免浮点误差 -
is_prime(1)必须返回false,is_prime(2)返回true,这是基础但常错 - 当
n是完全平方数(如 49 = 7 × 7),i == n / i,这时仍满足“两个素数相乘”,应返回true;你的is_prime要能正确处理7 - 对于大
n(比如 > 1e12),试除法太慢;此时需要 Miller-Rabin 判素 + Pollard-Rho 分解,但日常题目中n ≤ 1e9用上述方法足够
一个可直接粘贴的 C++ 实现
以下代码通过了常见测试用例(4, 6, 9, 10, 14, 15, 21, 25, 49, 121, 1, 2, 3, 8, 12, 16, 100):
bool is_prime(long long x) {
if (x bool is_semiprime(long long n) {
if (n <p>注意:<code>is_semiprime</code> 中的循环只会找到最小因子 <code>i</code>,因此后续只需验证这一对;不需要继续找其他因子——因为半素数的定义不关心因子顺序,只关心素因子总数是否为 2,而最小因子配对出来的商,就是唯一的另一因子(或其合数形式,此时 <code>is_prime(n/i)</code> 自动失败)。</p><p>最易忽略的一点:很多人写 <code>is_prime</code> 时忘记处理 <code>x == 2</code> 的特例,或把循环起始设成 2 而没跳过偶数,导致超时或误判;还有人用 <code>sqrt</code> 函数却不加 <code>llround</code> 或类型转换,在大数时出错。</p>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











