素数筛
素数又称质数,素数指除了1和他本身,不能被任何数整除的数,素数>=2,非素数叫做合数,比如16是合数,19是素数
学会了素数的几种筛法,你就可以像普奇神父一样随时让自己冷静下来(说不定想不起来有哪些质数而更加暴躁)
最最普通的做法:
一 .枚举
判断一个数n是否为素数,只需要用2~n-1的每一个数去除,若能被整除则不是素数:
int isPrime(int n){ if(n<=1) return 0; for(int i = 2;i<n;i++){ if(n%i==0) return 0; //0代表不是素数 } return 1; //1代表是素数 }
稍微优化:
若n可以被2~n-1的整数整除,其两个因子必然有一个大于等于√ n ,一个小于等于√ n
则有:
int isPrime(int n){ if(n<=1) return 0; for(int i = 2;i*i<=n;i++){ if(n%i==0) return 0; //0代表不是素数 } return 1; //1代表是素数 }
二. 埃氏筛(埃拉特斯特尼筛法)
素数的倍数都是合数,用一个数组来标记素数和合数,筛去所有的合数
比如:2的倍数:4,6,8,10
3的倍数:6,9,15,18
void isPrime(int n){//求0-n之间的素数 memset(prime,0,sizeof(prime));//用0表示素数 for(int i = 2;i*i<n;i++){ if(prime[i]==0){ for(int j = 2*i;j<=n;j+=i){ //这里的j+=i就相当于j是i的倍数:例如:4,6,8,10.每次加2,j每次加3i-2i=i; prime[j] = 1; } } } }
进一步优化:
看一看i = 5时,我们在第二层循环里筛去2*5,3*5,4*5,5*5等等,在i = 2,3,4时,已经有过5*2,5*3,5*4,所以我们第二层循环的起点设为i*i即可
void isPrime(int n){//求0-n之间的素数 memset(prime,0,sizeof(prime));//用0表示素数 for(int i = 2;i*i<n;i++){ if(prime[i]==0){ for(int j = i*i;j<=n;j+=i){ prime[j] = 1; } } } }
这样的埃氏筛仍然有重复判断:
我们来看一个效率更高的方法:
三.欧拉筛
一个合数可以分解为多个素数的乘积(简单的想一想:每个合数都有因数,因数中的非素数还可以继续分解,直到最后只剩下素数)
如:12 = 2*2*3
先写到这里,改日再来
学习的时候喜欢用Markdown做记录,存货已经堆满文件夹了

浙公网安备 33010602011771号