简单复习一下有关质数的知识
质数的定义
在大于1的自然数中,因数只有1和它本身的自然数。由这个定义可以得到,1不是质数,2是最小的质数。
判断质数
试除法
试除法是最快能想到的方法,这里的代码做了一点优化,即从2遍历到sqrt(n)而不是n-1。这是因为:如果n有一个大于sqrt(n)的因子,那么它必定有一个小于sqrt(n)的因子。因此,如果我们在2到sqrt(n)之间没有找到因子,那么大于sqrt(n)的范围内也不会找到因子。在遍历时需要判断i*i<=x,为了防止溢出,这里的写法是i<=x/i
#include<iostream>
using namespace std;
bool is_prime(int x)
{
if(x<2) return false;
else
{
for(int i=2;i<=x/i;i++)//从2遍历sqrt(x)
if(x%i==0) return false;
}
return true;
}
int main()
{
int n,x;
cin>>n;
int cnt=0;
while(n--)
{
cin>>x;
if(is_prime(x)) cnt++;
}
return cnt;
}质数筛
质数定理:在1~n之间有n/logn个质数
朴素筛法
原理:把所有要判断的数列出来,把每一个数的倍数删掉
对任意一个数P来说,如果它没有被删掉,则2~P-1都不是它的约数
时间复杂度O(nlogn)
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000010;
int primes[N],cnt;
bool st[N];
void get_primes(int n)
{
for(int i=2;i<=n;i++)
{
//如果这个数没有被筛过,说明它是质数
if(!st[i])
{
primes[cnt++]=n;
}
//把每一个数的倍数删掉
for(int j=i+i;j<=n;j+=i)
st[j]=true;
}
}
int main()
{
int n;
cin >> n;
get_primes(n);
cout << cnt << endl;
return 0;
}埃氏筛法
优化:在朴素筛法的基础上,只删除所有质数的倍数
//埃氏筛法
#include<iostream>
using namespace std;
const int N=1000010;
int primes[N],cnt;
bool st[N];
void get_primes(int n){
for(int i=2;i<=n;i++)
{
if(!st[i])
{
primes[cnt++]=i;
for(int j=i*i;j<=n;j+=i) st[j]=true;
//可以用质数把所有的合数都筛掉;
}
}
}
int main()
{
int n;
cin >> n;
get_primes(n);
cout << cnt << endl;
return 0;
}线性筛法
原理:从小到大枚举所有质数,筛掉这些质数的倍数
对于每一个合数n,只会被它的最小质因子筛掉
i % primes[j]==0:
primes[j]一定是i的最小质因子,primes[j]也一定是primes[j]*i的最小质因子
i % primes[j]≠0:
primes[j]一定小于i的所有质因子,primes[j]也一定是primes[j]*i的最小质因子
//线性筛法
#include<iostream>
using namespace std;
const int N=10000010;
int primes[N],cnt;
bool st[N];
void get_prime(int n)
{
for(int i=2;i<n;i++)
{
if(!st[i]) primes[cnt++]=i;
for(int j=0;primes[j]<n/i;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0)break;//primes[j]一定是i的最小质因子
}
}
}
int main()
{
int n;
cin>>n;
get_prime(n);
cout<<cnt<<endl;
}分解质因数
对于一个合数n,把它分解成$p_{1}^{n_{1}}*p_{2}^{n_{2}}$的形式并输出
#include<iostream>
#include<algorithm>
using namespace std;
void divide(int n)
{
for(int i=2;i<=n/i;i++)
if(n%i==0)
{
int s=0;
while(n%i==0)//i一定是质数
{
n/=i;
s++;
}
cout<<i<<' '<<s<<endl;
}
if(n>1)cout<<n<<<" "<1<<endl;
cout<<endl;
}
int main()
{
int n;
cin>>n;
while(n--)
{
int x;
cin>>x;
divide(x);
}
}