【数学】【数论】素数的线性筛法

写在前面

  记录了个人的学习过程,同时方便复习

  • 素数的线性筛法

  有时候需要筛出来一张素数表,即1~n范围内的所有素数

  一个个枚举判断是否为素数显然太慢

  于是经过仔细的研究之后,发现如果存在正整数k(k>2)不是素数,那么它的因子里面一定包含之前的素数

  这样的话,开一个boolean数组标记一下不是素数的数,筛到它们的时候跳过就好

详见埃拉托斯特尼筛法

  但是如果这样筛,显然会有重复的筛除啊

  比如6筛去了42,7也筛去了42

  这样的情况还有很多很多,十分影响效率,时间上并不是线性的

  但如果按照一个数的最小素因子把这个数排除掉,就没问题了!

  代码如下:

C++:

 1 #include<bits/stdc++.h>
 2
 3 using namespace std;
 4
 5 int const MAXN=100010;
 6
 7 int prime[MAXN],tot;
 8 bool notprime[MAXN];
 9
10 void pony_prime(int n){
11     notprime[0]=1;
12     notprime[1]=1;
13     for(int i=2;i<=n;++i){
14         if(!notprime[i])
15             prime[tot++]=i;
16         for(int j=0; j<tot && i*prime[j]<=n;++j){
17             notprime[i*prime[j]]=1;
18             if(i%prime[j]==0) break;
19         }
20      }
21 }
22
23 int main(int argc,char *argv[],char *enc[]){
24     int m=100;
25     pony_prime(m);
26     for(int i=1;i<=m;++i){
27         if(notprime[i]) printf("%d\n",i);
28         else printf("%d    Prime\n",i);
29     }
30     return 0;
31 }

Java:

 1 class pony{
 2
 3     static int MAXN=100010;
 4
 5     static int[] prime=new int[MAXN];
 6     static int tot=0;
 7     static boolean[] notprime=new boolean[MAXN];
 8
 9     static void pony_prime(int n){
10         notprime[0]=true;
11         notprime[1]=true;
12         for(int i=2;i<=n;++i){
13             if(!notprime[i])
14                 prime[tot++]=i;
15             for(int j=0; j<tot && i*prime[j]<=n;++j){
16                 notprime[i*prime[j]]=true;
17                 if(i%prime[j]==0) break;
18             }
19          }
20     }
21
22     public static void main(String[] args){
23         int m=100;
24         pony_prime(m);
25         for(int i=1;i<=m;++i){
26             if(notprime[i]) System.out.println(i);
27             else System.out.println(i+" Prime");
28         }
29     }
30
31 }

原文地址:https://www.cnblogs.com/Antigonae/p/10127134.html

时间: 2024-08-29 06:40:53

【数学】【数论】素数的线性筛法的相关文章

一般筛法求素数+快速线性筛法求素数

素数总是一个比较常涉及到的内容,掌握求素数的方法是一项基本功. 基本原则就是题目如果只需要判断少量数字是否为素数,直接枚举因子2 ..N^(0.5) ,看看能否整除N. 如果需要判断的次数较多,则先用下面介绍的办法预处理. 一般的线性筛法 首先先介绍一般的线性筛法求素数 void make_prime() { memset(prime, 1, sizeof(prime)); prime[0]=false; prime[1]=false; int N=31700; for (int i=2; i<

【转载】一般筛法求素数+快速线性筛法求素数

素数总是一个比较常涉及到的内容,掌握求素数的方法是一项基本功. 基本原则就是题目如果只需要判断少量数字是否为素数,直接枚举因子2 ..N^(0.5) ,看看能否整除N. 如果需要判断的次数较多,则先用下面介绍的办法预处理. 一般的线性筛法 首先先介绍一般的线性筛法求素数 void make_prime() { memset(prime, 1, sizeof(prime)); prime[0]=false; prime[1]=false; int N=31700; for (int i=2; i<

睡前数学一小时之线性筛素数:

睡前数学一小时之线性筛素数:1,朴素的筛素数算法:埃拉托斯特尼筛法.这是个简单再简单不过的一个素数的筛法.只是名字很拉风.这就告诉我们,往往东西不好这没什么,名字很拉风.别人也不会记住.hhhhh.这个的思路就是.每一个数都是由一个质数与和数(质数也可以)的积组成.这也是质数与和数的定义.而这个它这个筛发,就是当遇到一个质数的时候开始枚举,枚举[1,n]中间关于这个质数的倍数.每次都枚举,每次都将算出的这个数打上标记.而最后整个区间内的质数枚举完后,整个区间内的质数也就筛选出来了.这个很简单.时

欧拉线性筛法求素数(顺便实现欧拉函数的求值)

我们先来看一下最经典的埃拉特斯特尼筛法.时间复杂度为O(n loglog n) int ans[MAXN]; void Prime(int n) { int cnt=0; memset(prime,1,sizeof(prime)); prime[0]=prime[1]=0; for(int i=2;i<n;i++) { if(vis[i]) { ans[cnt++]=i;//保存素数 for(int j=i*i;j<n;j+=i)//i*i开始进行了稍微的优化 prime[j]=0;//不是素

线性筛法求素数

为什么称为线性,因为普通的筛法重复了好多次,冗余,而线性筛法避免了冗余. ①如果 i 都是是素数的话,那简单,一个大的素数 i 乘以不大于 i 的素数,这样筛除的数跟之前的是不会重复的.筛出的数都是 N=p1*p2的形式, p1,p2之间不相等 ②如果 i 是合数,此时 i 可以表示成递增素数相乘 i=p1*p2*...*pn, pi都是素数(2<=i<=n),  pi<=pj  ( i<=j )p1是最小的系数. 根据“关键处2”的定义,当p1==prime[j] 的时候,筛除就

数论 - 线性筛法与积性函数

首先以求1000000以内的素数为例来探讨筛法 Eratosthenes筛法(埃拉托斯特尼筛法) 时间复杂度:O(N*loglogN) 空间复杂度:O(N) 代码: #include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bit

素数的一般筛法和快速线性筛法

一般筛法: 1 void prime() { 2 memset(vis, true, sizeof(vis)); 3 vis[0] = vis[1] = false; 4 for (int i = 2; i < maxn; i++) { 5 for (int j = 2; i * j < maxn; j++) { 6 vis[i * j] = false; 7 } 8 } 9 } 快速线性筛法: 1 int prime[N] = {0}: 2 bool isNotPrime[N] = {1,

线性筛法(欧拉筛法)求素数

写$\text{O}\left( n \log{\log{n}}\right)$的筛法很长时间了,我却从来没想过它的优化.偶然间看到线性筛法,心想大约是不错的优化,于是便爬去学习下. 首先,$\text{O}\left( n \log{\log{n}}\right)$的筛法肯定要比$\text{O}\left( n\right)$的慢,虽然在现在的机子上不明显.还是不要将$\text{O}\left( n \log{\log{n}}\right)$比较靠谱.但是线性筛法有着它自己的用途.

线性筛法

关于线性筛法 线性是指O(n)内筛掉所有合数,还有一种方法叫埃氏筛法,我先证明埃氏筛法效率低,也就是会有重复. 证明如下: 埃氏筛法的原理是找到一个素数后,它的1~n倍就会被筛掉,任何一个合数都可以被拆成一个质数*合数的形式,我们对每一个质数对应的可能的(合)数都枚举了,这就保证了所有可能的合数都被筛掉了.为什么不是最优呢?问题出在那个质数上,对于一个合数m,m=h*P,P是质数且P>m的最小质因数,那么m也可以表示为m=H*p,(H是个比h大的合数,p是m的最小质因数),这样我们在枚举p的倍数