欧拉筛(线性筛)

素数筛,就是按照顺序把合数踢掉,剩下的是素数。

欧拉筛是一种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

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

【bzoj2401】陶陶的难题I “高精度”+欧拉函数+线性筛

题目描述 求 输入 第一行包含一个正整数T,表示有T组测试数据.接下来T<=10^5行,每行给出一个正整数N,N<=10^6. 输出 包含T行,依次给出对应的答案. 样例输入 7 1 10 100 1000 10000 100000 1000000 样例输出 1 2127 18446224 183011304660 1827127167830060 18269345553999897648 182690854273058293758232 题解 “高精度”+欧拉函数+线性筛 由于$i$和$j$

欧拉筛 线性筛 素数+莫比乌斯的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

欧拉函数+素数筛

欧拉函数,就是欧拉发现的一个关于求素数的的公式,然后我们编个函数实现这个公式. 欧拉发现求小于等于n的正整数中有多少个数与n互质可以用这个公式: euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数.euler(1)=1(唯一和1互质的数就是1本身). 欧拉公式的延伸:一个数的所有质因子之和是euler(n)*n/2. 其实直接看模板加注解想想就能看懂 筛选的原理就是找出n的因子,剔除含有

欧拉筛&amp;&amp;线性筛

复杂度 n 分析 其实就是把埃筛的改进罢了,避免重复 具体看代码 代码 #include<bits/stdc++.h> using namespace std; bool vis[10000000]; int prime[10000]; int Oulashai(int n){ memset(vis,0,sizeof(vis)); int cnt=0; for(int i=2;i<=n;i++){ if(!vis[i]) prime[cnt++]=i; for(int j=0;j<

欧拉函数线性筛法

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #define lli long long int 6 using namespace std; 7 const int MAXN=10000001; 8 void read(int &n) 9 { 10 char c='+';int x=0;bool flag=0; 11 while(c&l

质因数分解+欧拉筛+线性基

质因数分解: for(int i=2;i*i<=n;i++){ if(n%i==0) p.push_back(i); while(n%i==0) n/=i; } if(n!=1) p.push_back(n); 欧拉函数(线性筛): //欧拉函数 phi[x]代表[1,x]种与x互质的数的个数 void getphi() { phi[1]=1;int cnt=0; for(int i=2;i<=N;i++){ if(!vis[i]){prime[++cnt]=i;phi[i]=i-1;} fo

数论线性筛总结 (素数筛,欧拉函数筛,莫比乌斯函数筛,前n个数的约数个数筛)

线性筛 线性筛在数论中起着至关重要的作用,可以大大降低求解一些问题的时间复杂度,使用线性筛有个前提(除了素数筛)所求函数必须是数论上定义的积性函数,即对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数,若a,b不互质也满足的话则称作完全积性函数,下面说明每个筛子是怎么筛的. 最基础的是素数筛,其它三个筛都是以素数筛为前提 素数筛 void get_prime() { int pnum = 0; for(int i = 2;

【模版】线性筛(素数,欧拉函数,莫比乌斯函数)

线性筛: 线性筛是一种比较实用的筛法,它与数论中的(完全)积性函数密切相关: (完全)积性函数的定义:对于两个整数 \(x_1\) 和 \(x_2\) ,若有函数\(f(x)\)满足:\(f(x_1x_2)=f(x_1)f(x_2)\),我们称\(f(x)\)为完全积性函数:特殊的:若 \(x_1\) 和 \(x_2\) 一定为两个互质的正整数,我们称\(f(x)\)为积性函数! 而线性筛就是利用了这一性质,将\(f(x)\)用且只用\(x\)最小的那个质因子利用\(f(x_1x_2)=f(x_

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

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+

SIEVE 线性筛

今天来玩玩筛 英文:Sieve 有什么筛? 这里介绍:素数筛,欧拉筛,莫比乌斯筛,约数个数筛 为什么要用筛? 顾名思义,筛就是要漏掉没用的,留下有用的.最终筛出来1~n的数的一些信息. 为什么要用线性筛? 考虑最基础的线性筛素数,是O(n)的. 而一般的做法是: 1.对于每个m暴力枚举1~sqrt(m)看能否被整除.O(nsqrt(n)) 2.对于每个找到的素数,用它去将所有它的倍数的数都干掉.O(nlogn) 但是,即使是第二种,也有一个log 这是因为一个合数会被它的所有质因子筛一次.要重复