> 文章列表 > 质数算法(C/C++)

质数算法(C/C++)

质数算法(C/C++)

目录

1  分解质因数

2  打印质数

2.1  O(n^2)算法(暴力法)

2.2  O(nlogn)算法(埃氏筛)

2.3  O(n)算法(线性筛)


1  分解质因数

#include <bits/stdc++.h>
using namespace std;
int num,temp;
int main()
{scanf("%d",&num);temp=num;//保护 for(int i=2;i<=temp;i++){while(num%i==0){printf("%d ",i);num/=i;}}return 0;
}

说明:这里不需要担心没有筛选质数的问题,因为是从小到大循环,不可能存在分解出合数的情况(例如:2第一个循环,所有2的倍数都已经被筛选掉了,后续循环不可能再有2的倍数被num整除)

2  打印质数表

2.1  O(n^2)算法(暴力法)

两层循环,第一层循环i遍历大于等于2的所有数,第二层循环遍历大于1小于i的所有数j,判断i%j!=0一直成立,则该数为质数

这种方法虽然思路简单,但时间复杂度有时不能满足题目要求

2.2  O(nlogn)算法(埃氏筛)

定理:一个质数*任何一个不为1的正整数=合数

有了定理之后,就可以通过定理优化代码降低时间复杂度,下面是具体思路

Eratosthenes筛选方法(Eratosthenes Sieve Method)

假设有一个筛子存放1~N,例如:

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 .........N

先将  2的倍数  筛去:

2 3 5 7 9 11 13 15 17 19 21..........N

再将  3的倍数  筛去:

2 3 5 7 11 13 17 19..........N

 之后,再将5的倍数筛去,再来将7的质数筛去,再来将11的倍数筛去........,如此进行到最后留下的数就都是质数,这就是Eratosthenes筛选方法(Eratosthenes Sieve Method)。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int primes[1000000];
int cnt;
bool notprime[1000000];void set_prime()
{notprime[1]=true;for(int i=2;i<1000000;i++){if(!notprime[i]){primes[++cnt]=i;}for(ll j=(ll)i*i;j<1000000;j+=i)//保证每一个遍历的值都没被筛过{notprime[j]=true;}}
} int main()
{set_prime();for(int i=1;i<=cnt;i++){cout<<primes[i]<<endl;}return 0;
}

 模拟发现,有一些数被筛了不止一次,可能还有更优解

2.3  O(n)算法(线性筛)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int primes[1000000];
bool notprime[1000000];
int cnt,n;
int main()
{cin>>n;//打印范围 for(int i=2;i<=n;i++){if(!notprime[i])	primes[++cnt]=i;for(int j=1;j<=cnt&&i*primes[j]<=n;j++){notprime[i*primes[j]]=true;if(i%primes[j]==0)	break;}}for(int i=1;i<=cnt;i++){cout<<primes[i]<<endl; }return 0;
}