质数算法(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;
}