简单复习一下有关质数的知识

质数的定义

在大于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);
    }
}
最后修改:2025 年 10 月 31 日
如果觉得我的文章对你有用,请随意赞赏