素数筛,就是按照顺序把合数踢掉,剩下的是素数。
欧拉筛是一种O(n)求素数的筛法。他避免了埃拉特斯特尼筛法对同一数的多次筛除。
欧拉筛的原理是只通过数的最小质因数筛数。
先上代码:
#include <cstdio> using namespace std; const int maxn=10000000; int n, m, prime[maxn], isnt_prime[maxn], tot; void get_prime(int n){ isnt_prime[0]=isnt_prime[1]=1; for (int i=2; i<=n; ++i){ if (!isnt_prime[i]) prime[++tot]=i; for (int j=1; j<=tot&&i*prime[j]<=n; ++j){ isnt_prime[i*prime[j]]=1; if (i%prime[j]==0) break; } } } int main(){ scanf("%d%d", &n, &m); get_prime(n); int t; for (int i=0; i<m; ++i){ scanf("%d", &t); if (!isnt_prime[t]) printf("Yes\n"); else printf("No\n"); } return 0; }
对于当前处理数i,我们将i分解成p1*p2*p3……,当前枚举素数为p[j]。
由于j从小到大枚举,直到i%p[j]==0前,p[j]都是i*p[j]的最小质因数。
在i%p[j]==0后,由于p[j]不是i*p[j]的最小质因数,i*p[j]必然可以被一个更小的质数q筛去。而i*p[j]/q必然会在后面被访问。所以不用遍历。
如何证明复杂度呢?由于2道n区间内的每一个数,都一定只被最小质因数筛掉,所以第二个for循环均摊到n个元素上的时间复杂度是O(1),总时间复杂度就是O(N)。
这是本人对欧拉筛的一点理解,如果有更好的方法或解释,欢迎在评论区评论。。
时间: 2024-12-24 08:39:22