素数:仅能被1和它本身整除的数叫做素数,否则是合数。
素数判断:一个数n,将所有小于n大于1的数逐个带入,如果有任意一个能整除,判断是合数,如果都不能,是素数。
优化:一个合数的因子是成对出现的(假设n=i*j;i<j;当我们判断i是n的一个因子时,同时也判断了j是n的一个因子),所以我们不必判断从2到n-1的所有数,判断2到sqrt(n)即可。
bool isprim(unsigned x) { if(x<2)return false; for(unsigned i=2;i*i<=x;i++) if(x%i==0)return false; return true; }
有时候,程序里需要反复检查一个数是否为素数,可以把判断结果保存在数组里,方便查询。这就是素数的筛法。
埃氏筛法:O(n log n),筛选出不是素数的数。有的数会被重复筛选,比如12:2*6=3*4=12;所以12会被2和3筛选到。
const int maxn=1000009; bool noprime[maxn]; void isprim() { memset(noprime,0,sizeof(noprime)); noprime[0]=noprime[1]=1; for(int i=2;i*i<maxn;i++) if(!noprime[i]) for(int j=i*i;j<maxn;j+=i) noprime[j]=true; }
欧拉筛/线性筛:O(n),利用质因数分解,任何一个整数都有他唯一的质因数表示法,所以就保证了每个数只被筛选一次。
const int maxn=100009; int prime[maxn+1]; //prime[0]用来储存素数个数 void getPrime() { memset(prime,0,sizeof(prime)); for(int i=2;i<=maxn;i++){ if(!prime[i])prime[++prime[0]]=i; for(int j=1;j<=prime[0]&&prime[j]*i<=maxn;j++){ prime[prime[j]*i]=1; if(i%prime[j]==0)break; } } }