判断素数
1.对于判断一个数n是否为素数,最朴素的方法是按素数的定义,试除以从2开始到m-1的整数,如果无一例外地不能整除,则该数一定是素数。
质数(prime number)又称素数,有无限个。
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。
#include<iostream> using namespace std; int n; int main(){ cin>>n; for( int i=2 ; i<=n ; ++i ){ if( n%i==0 ){ cout<<n<<" isn't a prime "<<endl; return 0; } } cout<<n<<" is a prime "<<endl; return 0; }
2.想一想,若2都不能除尽,还要试4, 6, 8, …吗?若3都不能除尽,还要试9, 15, 21, …吗?一个数,如果有因子的话,那么在它的平方根数以内就应该有,否则就没有因子。所以必定有一个因子不大于m的平方根。故判断m是否为素数,只要试除到m的平方根就可以了,不必一直到m-1。
#include<iostream> #include<cmath> using namespace std; int n; int main(){ cin>>n; for( int i=2 ; i<=sqrt(n) ; ++i ){ if( n%i==0 ){ cout<<n<<" isn't a prime "<<endl; return 0; } } cout<<n<<" is a prime "<<endl; return 0; }
3.另一种判断素数的方法–筛法。从文件prime.txt中读入一些整数,然后判断其是否为素数。从2开始的某个连续整数集合,留下2,除去所有2的倍数,留下3,除去所有3的倍数,留下5,再除去所有5的倍数,如此等等。留下某个最先遇到的素数,将其所有的倍数从该数集中去掉。最后,数集中就全是素数了。接下来,要判断一个数是否为素数,可以该数为下标,访问素数集合。如果是,则为素数,否则不是素数。
【普通筛——埃拉托斯特尼(Eratosthenes)筛法】 时间复杂度O(nloglogn)
#include<iostream> using namespace std; int n; bool prime[10086]; int main(){ cin>>n; for( int i=2 ; i<=n ; ++i ){ if( !prime[i] ){ for( int j=2 ; j*i<=n ; ++j ){ prime[i*j]=1; } } } return 0; }
【线性筛——欧拉Euler筛】 时间复杂度为O(n)
prime[]数组中的素数是递增的,当i能整除prime[j],那么i*prime[j+1]这个合数肯定被prime[j]乘以某个数筛掉。因为i中含有prime[j],prime[j]比prime[j+1]小,即i=k*prime[j],那么i*prime[j+1]=(k*prime[j])*prime[j+1]=k’*prime[j],接下去的素数同理。所以不用筛下去了。因此,在满足i%prime[j]==0这个条件之前以及第一次满足改条件时,prime[j]必定是prime[j]*i的最小因子。
#include<iostream> using namespace std; int n; int prime[10086],c; bool num[10086]; int main(){ cin>>n; for( int i=2 ; i<=n ; ++i ){ if( !num[i] ) prime[++c]=i; for( int j=1 ; i*prime[j]<=n && j<=c ; ++j ){ num[ i*prime[j] ] = 1; if( i%prime[j]==0 ) break; } } for( int i=1 ; i<=c ; ++i ){ cout<<prime[i]<<" "; }
return 0; }