只需试除到√n,因若n有大于√n的因子,则必有小于√n的对应因子,时间复杂度降为o(√n),需注意n=1和完全平方数的边界处理。

用 sqrt 优化试除法,别从 2 试到 n−1
直接遍历到 n-1 判断整除,时间复杂度是 O(n),对大一点的数(比如 10⁶)就明显卡顿。实际只需试到 sqrt(n):如果 n 有大于 sqrt(n) 的因子,那它一定对应一个小于 sqrt(n) 的因子。
注意边界处理:n 不是素数;<code>n == 2 是唯一偶素数;所有其他偶数直接返回 false。
实操建议:
- 用
int i = 2; i * i 替代 <code>i ,避免浮点误差和类型转换开销 - 先特判
n == 2,再用n % 2 == 0排除其余偶数,后续循环只检查奇数 - 对于
n == 1、n == 0、负数,统一返回false
写成函数时,输入类型选 long long 更稳妥
很多题或实际场景中,要判断的数可能接近 INT_MAX(约 2×10⁹),这时 i * i 容易溢出——哪怕 i 是 int,平方后也可能超限。
实操建议:
- 函数参数用
long long n,内部循环变量也用long long i,确保i * i 不溢出 - 如果确定输入不会超
int,且追求极致性能,可用unsigned int配合i (避免乘法) - 不要用
double sqrt(n)后转int,比如n = 999999999999999999时,sqrt可能精度丢失导致漏判
遇到多次查询?预处理 bool is_prime[] 比单次调用快得多
如果要在程序里反复判断不同数字是否为素数(比如处理 10⁵ 个数),每次都调用上面的函数,最坏情况总耗时可能达 O(N√M),远不如一次性筛出范围内的所有素数。
实操建议:
- 若最大待查数为
M,用埃氏筛(vector<bool> is_prime(M+1, true)</bool>)时间复杂度 O(M log log M) - 注意初始化:设
is_prime[0] = is_prime[1] = false,从i = 2开始筛,只筛到sqrt(M) - 内存敏感时改用分段筛,但一般
M 直接用普通埃氏筛足够
常见错误:把 1 当作素数,或忽略负数和 0
标准定义中,素数是「大于 1 的正整数,且只有 1 和它本身两个正因数」。所以 0、1、负数一律不是素数——但很多人写的函数没显式处理这些,导致 is_prime(1) 返回 true 或崩溃。
典型错误现象:
-
is_prime(1)返回true(循环没进,直接 return true) -
is_prime(-5)进入循环,i * i 永假或行为未定义 -
is_prime(2)被if (n % 2 == 0)错误拦截,返回 false
最简健壮写法开头应为:if (n ,然后特判 <code>n == 2,再处理偶数。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











