数学技巧之素数筛选

如果只是对一个整数进行素性测试的只要o(√n)的复杂度便可以判定,蓝而如果是n个呢(n<=1000)照样可以,那如果100000个呢?对于普通的o(n√n)根本跑不动,因此我们必须寻找更加高效的算法,常用的筛选方法有埃氏筛法, 区间筛法,欧拉筛法。

1.埃氏筛法

首先,我们先把2-n范围内的数写下来,其中最小的素数是2,那么能被2整除的数便不是素数,那么我们可以把2的倍数都划去。然后剩下的最小素数便是3,我们便把3的倍数都划去,以此类推。这样反复操作我们就能枚举n以内的素数。

贴上伪代码:

1 const int N = 1000000 + 5;
2 int check[N], prime[N];
3
4 int ptot = 0;
5 memset(check, 0, sizeof(check));
6 for(int i = 2; i <= n; i ++){
7     if(!check[i])prime[ptot++] = i;
8     for(int j = 2; i * j <= n; j ++) check[i * j] = 1;
9 }

但是问题又来了, 这个复杂度究竟该怎么算呢?怎么看像o(n2)呢?No No No~~

每次我们筛去每个数的整数倍像2筛了n/2个,3筛了n/3个;

因此总的复杂度约为:

哎呀!这不是发散级数吗?这个不是发散的数啊,那复杂度不是会爆掉吗?

别担心,虽然它是发散级数,但是他的增长速度非常慢,来我们测试一下

看到了吗?这个发散级数在n = 1000000的时候都没有超过14由此可见它的复杂度很小,近似等效成o(nloglogn),而对我们这些搞ACM得人来书讲他大致看成线性的都无妨。

2.区间筛法

设区间[a,b)表示a<=x<b,的素数所构成的集合。

我们很容易知道b只要不能整除[2,√b]里面的素数,那么b就可以被认定为一个素数,因此,如果我们有√b里面的素数表,便可以结合埃氏筛法来判断。

附上伪代码:

 1 const int N = 100000 + 5;
 2 int check[N], prime[N];
 3 int is_prime[N];
 4
 5 int ptot = 0;
 6 memset(check, 0, sizeof(check));
 7 memset(is_prime, 0, sizeof(is_prime));
 8 for(int i = 2; i <= n; i ++){
 9     if(!check[i])prime[ptot++] = i;
10     for(int j = 2; i * j <= sqet(b); j ++) check[i * j] = 1;//筛[2,√b)
11     for(int j = a/i+1; i * j < b; j ++) is_prime[i * j - a] = 0;//筛[a,√b)
12     //将[a, b)的数,移到[0, b - a)可节省空间
13 }

3.欧拉筛法

这便是重头戏,真真正正的o(n)的复杂度去大范围筛选素数

什么都不说,先上代码

 1 const int N = 100000 + 5;
 2 int check[N], prime[N];
 3
 4 int ptot = 0;
 5 memset(check, 0, sizeof(check));
 6 memset(is_prime, 0, sizeof(is_prime));
 7 for(int i = 2; i <= n; i ++){
 8     if(!check[i])prime[ptot++] = i;
 9     for(int j = 0; j < ptot; j ++){
10         if(prime[j] * i  > n) break;
11         check[prime[j] * i] = 1;
12         if(i % prime[j] == 0)break;
13     }
14 }

这个貌似只是做了少许改进了吧,貌似就改进了第12行啊,聪明,蓝而就是因为这一行,导致了他的复杂度变成完美的线性, 设合数的最小质因数为p,则当它遍历到这个素数的时候因为第12行二跳出循环,这样直接导致了每个合数只能被它的最小质因数给删去。

下面给出证明:

设合数n的最小质因数为p,另一个比它大的质因数为p1,设 n = p1 * m1 = p * m,我们很容易就可以发现j循环到质因数p的时候合数n第一次被标记(若循环到p之前已经跳出循环则说明有比p更小的质因数),若也被p1标记,则是在这之前(因为p1 > p,所以m1 < m),考虑i循环到m1,注意到n = p*m=p1*m1且p,p1为不同的质数,因此p|m1,所以当j循环到质数p后就结束,不会循环到p1.这就说明了不会被p1筛去,说明合数只能被它最小的合数给删去。(很神奇吧!)

时间: 2024-10-05 16:22:02

数学技巧之素数筛选的相关文章

O(N)的素数筛选法和欧拉函数

首先,在谈到素数筛选法时,先涉及几个小知识点. 1.一个数是否为质数的判定. 质数,只有1和其本身才是其约数,所以我们判定一个数是否为质数,只需要判定2~(N - 1)中是否存在其约数即可,此种方法的时间复杂度为O(N),随着N的增加,效率依然很慢.这里有个O()的方法:对于一个合数,其必用一个约数(除1外)小于等于其平方根(可用反证法证明),所以我们只需要判断2-之间的数即可. bool is_prime(int num) { const int border = sqrt(num); for

关于素数的快速查找——素数筛选法

利用素数筛选法进行素数的快速查找.原理很简单,素数一定是奇数,素数的倍数一定不是素数.思路如下: 预定义N表示10000,即表示查找10000以内的素数,首先定义数组prime[]对N以内的数进行标记,奇数存为1,偶数存为0,最终实现结果为素数的prime值为1,因此将prime[2]赋值为1(2是素数).之后利用for循环,对N以内的奇数进行遍历(注意for循环的条件控制),for里用if判断是否为素数(奇数),若是,执行内部嵌套的for循环判断该奇数是否为素数,若是则标记为1,若不是则pri

(转载)O(N)的素数筛选法和欧拉函数

转自:http://blog.csdn.net/dream_you_to_life/article/details/43883367 作者:Sky丶Memory 1.一个数是否为质数的判定. 质数,只有1和其本身才是其约数,所以我们判定一个数是否为质数,只需要判定2~(N - 1)中是否存在其约数即可,此种方法的时间复杂度为O(N),随着N的增加,效率依然很慢.这里有个O()的方法:对于一个合数,其必用一个约数(除1外)小于等于其平方根(可用反证法证明),所以我们只需要判断2-之间的数即可. 1

hdu 5407 CRB and Candies(素数筛选法,除法取模(乘法逆元))

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5407 解题思路: 官方题解: The problem is just to calculate g(N) =\ LCM(C(N,0), C(N,1), ..., C(N, N))g(N) = LCM(C(N,0),C(N,1),...,C(N,N)). Introducing function f(n) =\ LCM(1, 2, ..., n)f(n) = LCM(1,2,...,n), the

[email&#160;protected] Sieve of Eratosthenes (素数筛选算法) &amp; Related Problem (Return two prime numbers )

Sieve of Eratosthenes (素数筛选算法) Given a number n, print all primes smaller than or equal to n. It is also given that n is a small number. For example, if n is 10, the output should be “2, 3, 5, 7″. If n is 20, the output should be “2, 3, 5, 7, 11, 13,

HDU 2161 Primes (素数筛选法)

题意:输入一个数判断是不是素数,并规定2不是素数. 析:一看就很简单吧,用素数筛选法,注意的是结束条件是n<0,一开始被坑了... 不说了,直接上代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; typedef long long LL; const int maxn = 16000 + 10; int p

LightOJ 1341 - Aladdin and the Flying Carpet (唯一分解定理 + 素数筛选)

http://lightoj.com/volume_showproblem.php?problem=1341 Aladdin and the Flying Carpet Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice LightOJ 1341 Description It's said that Aladdin had to solve seven

Light OJ 1197 1197 - Help Hanzo(大区间素数筛选)

Amakusa, the evil spiritual leader has captured the beautiful princess Nakururu. The reason behind this is he had a little problem with Hanzo Hattori, the best ninja and the love of Nakururu. After hearing the news Hanzo got extremely angry. But he i

素数筛选(模板)

#include <stdio.h> int main() { int i,j,a[505]={0}; for(i=1;i<=500;i++) a[i]=1; for(i=2;i<=500;i++) if(a[i]) for(j=i+i;j<=500;j+=i) a[j]=0; for(i=2;i<=500;i++) if(a[i]) printf("%d ",i); printf("\n"); return 0; } 素数筛选(