质数筛

质数筛

埃氏筛

思想

  • 对于一个正整数,除它本身外的所有正整数倍的数字一定都是合数

算法实现

我们利用 notprime[i] 表示一个数字是否为合数\(0\)质数\(1\)合数),所以:

bool notprime[maxn + 5]; // 初始均为 0:质数
for (int i = 2;i <= n;i ++) 
  if (notprime[i])
  	for (int j = 2;i * j <= n;j ++) // 枚举倍数
    	notprime[i * j] = true; // 筛出合数

埃氏筛的时间复杂度可以表示为 \(O(\cfrac{n}{2}+\cfrac{n}{3}+\cdots+\cfrac{n}{n})\approx O(n\ln(n))\)

线性筛

思想

在埃氏筛中,一个合数会被反复标记(合数有不同的拆分方式,如 \(12=2\times6或3 \times4或\cdots\)),这显然浪费了时间

在线性筛中,对于一个合数,我们在它的所有质因数中选出最小的一个 \(q\) ,此时被分解成 \(p\times q\) 的形式

算法实现

\(p\) 的因数中含有 \(q\) 时(p % q == 0),不再考虑 \(p\) 的其它倍数,直接跳出

bool notprime[maxn + 5]; // 初始均为 0:质数
int prime[maxn + 5],cnt = 0; // 记录质数
for (int i = 2;i <= n;i ++) {
	if (!notprime[i]) prime[++ cnt] = i; // 保存质数
  for (int j = 1;j <= cnt && i * prime[j] <= n;j ++) { // 枚举质因数
    notprime[i * prime[j]] = true; // 标记合数
    if (i % prime[j] == 0) break; // 跳出
  }
}

由于所有数仅标记一次,线性筛的时间复杂度线性复杂度 \(O(n)\)

posted @ 2025-05-25 22:49  nightmare_lhh  阅读(15)  评论(0)    收藏  举报