//#define fre yes #include <cstdio> const int N = 100005; int prime[N], isNotprime[N]; void isprime(int n) { int cnt = 0; isNotprime[1] = 1; for (int i = 2; i <= n; i++) { if(!isNotprime[i]) prime[++cnt] = i; for (int j = 1; j <= cnt && i * prime[j] <= n; j++) { isNotprime[i * prime[j]] = 1; if(i % prime[j] == 0) break; } } }
谈论数论不废话 ----- 线性筛
以上代码的时间复杂度是 \(O(n)\)
需要注意以下几点
- 1为素数,不为质数
- 如果当前不是素数,那么一定是质数(显然可得)
- 第二层循环中 为什么是 \(i \times prime[j] <= n\) 因为循环内用到了这个乘
最重要的是最后一句 \(i \mod prime[j] == 0\) 这句话是什么意思
我们可以假设没有这句话,那么当发生 \(i\mod prime[j] == 0\) 的时候,我们就知道 这个 \(i\) 必定包含 \(prime[j]\) 这样也就说明了此时 \(i\) 是 \(prime[j]\) 的最小因子,当到 \(prime[j + 1]\) 的时候,我们知道 \(i\) 是 \(prime[j]\) 的因子,原式子就可以改写成 \(prime[j + 1] \times i = prime[j + 1] \times k \times prime[j]\) 如果不跳过\(i \mod prime[j]\) 这里就会进行重复标记,很明显 这是我们不想看到的