一、质数
1.定义:若一个正整数无法被除了1和它自身之外的任何自然数整除,则称该数为质数(或素数),否则称该正整数为合数。
在整个自然数集合中,质数的数量不多,分布比较稀疏,对于一个足够大的整数N,不超过N的质数大约有N/lnN个,即每lnN个数中大约有1个质数。
2.质数的判定:试除法
若一个正整数N为合数,则存在一个能整除N的数T,其中2<=T<=sqrt(n)。
证明:
由定义得,因为N是合数,所以存在一个能整除N的数M,其中2<=M<=N-1。
反证法。假设命题不成立,那么这样的数M一定满足sqrt(n)+1<=M<=N-1.
因为M能整除N,所以它们的商N/M也能整除N。而2<=N/M<=sqrt(n),令T=N/M,这与假设矛盾。
故假设不成立,原命题成立。
证毕。
根据上述命题,我们只需要扫描2~sqrt(n)之间的所有整数,依次检查它们能否整除N,若都不能整除,则N是质数,否则N是合数。
复杂度O(sqrt(n))。
1 bool judge(int n){ 2 for(int i=2;i<=sqrt(n);i++){ 3 if(n%i==0) return 0; 4 } 5 return 1; 6 }
其他高效率随机算法:Miller-Robbin
3.质数的筛选
(1)Eratosthenes筛法
Eratosthenes筛法基于这样的想法:任意整数x的倍数2x,3x,…都不是质数。根据质数的定义,上述命题显然成立。
我们可以从2开始,由小到大扫描每个数x,把它的倍数2x,3x,…,[N/x]·x标记为合数。
当扫描到一个数时,若它尚未被标记,则它不能被2~x-1之间的任何数整除,该数就是质数。
1 void Eratosthenes(int n){ 2 memset(v,0,sizeof(v)); 3 for(int i=2;i<=n;i++){ 4 if(v[i]) continue ; 5 cout<<i<<' '; 6 for(int j=1;j<=n/i;j++) v[i*j]=1; 7 } 8 }
实际上,小于x^2的x的倍数在扫描更小的数时就已经被标记过了。
因此,我们可以对Eratosthenes筛法进行优化,对于每个数x,我们只需要从x^2开始,把x^2,(x+1)*x,[N/x]·x标记为合数即可。
Eratosthenes筛法的时间复杂度为O(NloglogN)。
(2)线性筛法
我们在生成一个需要标记的合数时,每次只向现有的数中乘上一个质因子,并且让它是这个合数的最小质因子。
具体地说,我们采用如下的线性筛法,其中v数组记录每个数的最小质因子。每个合数只会被它的最小质因子筛一次,时间复杂度为O(N)。
1 int v[N],prime[N],cnt; 2 void primes(int n){ 3 memset(v,0,sizeof(v)); 4 cnt=0; 5 for(int i=2;i<=n;i++){ 6 if(!v[i]){ 7 v[i]=i,prime[++cnt]=i; 8 } 9 for(int j=1;j<=m;j++){ 10 if(prime[j]>v[i]||prime[j]>n/i) break ; 11 v[i*prime[j]]=prime[j]; 12 } 13 } 14 for(int i=1;i<=cnt;i++){ 15 cout<<prime[i]<<' '; 16 } 17 }
4.质因数分解
(1)算术基本定理
任何一个大于1的正整数都能唯一分解为有限个质数的乘积,可写作:
N=p1^c1*p2^c2…pm^cm
其中ci都是正整数,pi都是质数,且满足p1<p2<…<pm
(2)试除法
结合质数判定的“试除法”和质数筛选的“Eratosthenes筛法”,我们可以扫描2~sqrt(n)的每个数d,若d能整除N,则从N中除掉所有的因子d,同时累计除去的d的个数。
因为一个合数的因子一定在扫描到这个合数之前就从N中被除掉了,所以在上述过程中能整除N的一定是质数。
最终就得到了质因数分解的结果,易知时间复杂度为O(sqrt(n))。
特别地,若N没有被任何2~sqrt(n)的数整除,则N是质数,无需分解。
1 void divide(int n){ 2 cnt=0; 3 for(int i=2;i<=sqrt(n);i++){ 4 if(n%i==0){ 5 prime[++cnt]=i,c[cnt]=0; 6 while(n%i==0) n/=i,c[cnt]++; 7 } 8 } 9 if(n>1){ 10 prime[++cnt]=n,c[cnt]=1; 11 } 12 for(int i=1;i<=cnt;i++){ 13 cout<<prine[cnt]<<'^'<<c[i]<<endl; 14 } 15 }
进阶:“Pollard's Rho”算法