线性筛素数(欧拉筛)

线性筛素数(欧拉筛)

欧拉筛为啥是\(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){  //当前数是所有数小于n的数而不只是素数,这是欧拉筛与埃氏筛的区别
        if (!isnt_prime[i]) prime[++tot]=i;
        for (int j=1; j<=tot&&i*prime[j]<=n; ++j){  //当前数乘上的素数为prime[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=p_1^{\alpha_1}p_2^{\alpha_2}...p_k^{\alpha_k}\ (p_1<p_2<...<p_k)\),当前枚举的i要乘上的素数为\(p_j\),那么,我们要筛掉的数就是\(i*p_j\)。

if (i%prime[j]==0) break;

这一行很重要。欧拉筛的特点,在于每个合数都被它的最小质因数筛掉。假设,当前被筛的数为\(x=i*p_j\)。如果\(p_j>p_1\),意味着\(p_j\)并不是x的最小质因数,等到i变的更大,变成某个\(i'\),x是可以被\(i'*p_1\)筛掉的。因此,如果发现\(p_j>p_1\),就没有必要再继续枚举p下去了。代码的含义其实相同:如果\(p_j\mid i\),意味着\(p_j=p_1\),因此后面枚举的\(p_j\)都大于等于\(p_1\),就不用继续枚举p了。

原文地址:https://www.cnblogs.com/MyNameIsPc/p/9314082.html

时间: 2024-10-03 23:28:49

线性筛素数(欧拉筛)的相关文章

线性筛素数(欧拉筛)+前缀和优化

关于素数的定义:在大于1的自然数中,除了1和它本身以外不再有其他因数. 判断一个数是否是素数: 1 int x; // 要求的数 2 for(int i=2;i<=sqrt(x);++i) 3 { 4 if(x%i==0) 5 { 6 cout << "这不是素数" << endl; 7 break; 8 } 9 } 埃氏筛法(时间复杂度:$O(NloglogN)$): 1 int num_prime = 0; // 素数的数量 2 int prime[5

素数表的获取(埃氏筛和欧拉筛)

Eratosthenes筛法(埃氏筛) 时间复杂度:O(nlognlogn) 思路 代码 const int maxn=1e6+10; //表长 int prime[maxn],cnt=0; //prime数组存放所以素数,cnt为素数个数 bool st[maxn]; //false为素数 void get_prime(int n){ for(int i=2;i<=n;i++){ if(!st[i]){ prime[cnt++]=i; //把素数i存到prime数组中 for(int j=i+

线性筛素数-欧拉筛法

1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 int num[100000]; 5 long long prime[5000001]; 6 bool is_prime[10000001]; 7 int N,M; 8 int cnt=1; 9 int main() 10 { 11 for(int k=0;k<10000001;k++) 12 { 13 is_prime[k]=true; 14

[洛谷P3383]线性筛素数-欧拉筛法

Description 如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内) Input&Output Input 第一行包含两个正整数N.M,分别表示查询的范围和查询的个数. 接下来M行每行包含一个不小于1且不大于N的整数,即询问该数是否为质数. Output 输出包含M行,每行为Yes或No,即依次为每一个询问的结果. Solution 代码如下: #include<iostream> #include<cstring> using n

欧拉筛 线性筛 素数+莫比乌斯的mu[]

https://blog.csdn.net/qq_39763472/article/details/82428602 模板来自https://blog.csdn.net/Avalon_cc/article/details/81663214 bool isP[N]; int P[N], ind; void Euler() { mem(isP,1); mu[1]=1; ind=0; for(int i=2;i<N;i++) { if(isP[i]) P[ind++]=i, mu[i]=-1; for

线性(欧拉)筛&amp;欧拉函数

线性筛法 what is 线性筛??就是基于最基本的筛法的优化. 在基础的筛法上,我们发现有的数字会被重复筛,例如6既会被2枚举到也会被3枚举到,必然有重复运算. 我们的做法就是让每一个数的最小因数筛. \(FOR\) \(EXAMPLE:\) 有一个数\(2 * 2 * 3 * 5\) 有另一个数 \(3 * 3 * 3* 5\) 那么第一个数枚举到3的话,筛到的数字是\(2 * 2 * 3 * 3 * 5\) 但是在第二个数字再次枚举的时候 枚举到2时 也会枚举到\(2 * 2 * 3 *

Goldbach&#39;s Conjecture POJ - 2262 线性欧拉筛水题 哥德巴赫猜想

题意 哥德巴赫猜想:任一大于2的数都可以分为两个质数之和 给一个n 分成两个质数之和 线行筛打表即可 可以拿一个数组当桶标记一下a[i]  i这个数是不是素数  在线性筛后面加个装桶循环即可 #include<cstdio> #include<cstring> using namespace std; bool Is_Primes[1000005]; int Primes[1000005]; int cnt; void Prime(int n){ cnt=0; memset(Is_

欧拉线性筛 和 欧拉函数的求值

PS:求逆元的部分在文章最后...最好也看看前边的知识吧qwq 用筛法求素数的基本思想是:把从1开始的.某一范围内的正整数从小到大顺序排列, 1不是素数,首先把它筛掉.剩下的数中选择最小的数是素数,然后去掉它的倍数.依次类推,直到筛子为空时结束.(来自 百度百科) 一般的筛法(埃拉托斯特尼筛法)的效率是O(nlglgn),但出题人卡你可就凉了.. (就不介绍了(逃)) 下面我们来说O(n)的欧拉线性筛 埃筛之所以慢,是因为有些合数被重复筛除(如:6会被2和3重复筛) 但是欧拉筛保证 每一个数p,

素数筛&amp;&amp;欧拉筛 BZOJ2818 Gcd BZOJ2190 [SDOI2008]仪仗队

折腾了一晚上很水的数论,整个人都萌萌哒 主要看了欧拉筛和素数筛的O(n)的算法 这个比那个一长串英文名的算法的优势在于没有多次计算一个数,也就是说一个数只筛了一次,主要是在%==0之后跳出实现的,具体的解释看的迷迷糊糊,特别是欧拉函数的求解 http://blog.csdn.net/lerenceray/article/details/12420725 代码如下 1 void ES(){ 2 for(int i=2;i<n;i++){ 3 if (!pd[i]){ 4 prime[++top]=