「AcWing学习记录」质数

AcWing 866. 试除法判定质数

原题链接

时间复杂度O(n)

d|nnd|n

dndd2ndn

#include<iostream>
#include<algorithm>

using namespace std;

bool is_prime(int n)
{
    if(n < 2) return false;
    for(int i = 2; i <= n / i; i++)
        if(n % i == 0)
            return false;
    return true;
}

int main()
{
    int t;
    scanf("%d", &t);

    while(t--)
    {
        int a;
        scanf("%d", &a);
        if(is_prime(a)) puts("Yes");
        else puts("No");
    }

    return 0;
}

AcWing 867. 分解质因数

原题链接

时间复杂度介于O(logn)O(n)之间

#include<iostream>
#include<algorithm>

using namespace std;

void divide(int n)
{
    for(int i = 2; i <= n / i; i++)
        if(n % i == 0) //i一定是质数
        {
            int s = 0;
            while(n % i == 0)
            {
                n /= i;
                s++;
            }

            printf("%d %d\n", i, s);
        }

    if(n > 1) printf("%d %d\n", n, 1); //n中最多只包含一个大于sqrt(n)的质因子,可通过反证法证明
    puts("");
}

int main()
{
    int t;
    scanf("%d", &t);

    while(t--)
    {
        int a;
        scanf("%d", &a);

        divide(a);
    }

    return 0;
}

AcWing 868. 筛质数

原题链接

对于一个大于2的正整数p,如果p没有被筛掉,那么说明p不是2到p-1中任何一个数的倍数,即2到p-1中没有一个数是p的约数。

朴素筛法的时间复杂度计算

n2+n3++nn=n(12+13++1n)

limn(12+13++1n)=lnn+C

C为欧拉常数,约为0.577

nlnn<nlog2n

时间复杂度可以记成O(nlogn)


埃氏筛法的时间复杂度计算
质数定理:1~n中有nlnn个质数

n(12+13++1n)=nlnn/lnn=O(n)

而真实的时间复杂度为O(nloglogn)


线性筛法的原理
1.i % pj == 0
pj一定是i的最小质因子,pj一定是pj * i的最小质因子
2.i % pj != 0
pj一定小于i的所有质因子,pj也一定是pj * i的最小质因子

对于一个合数x,假设pj是x的最小质因子,当i枚举到x/pj的时候一定会被筛掉,所以任何一个合数都会被筛掉,并且只用最小质因子来筛,每个数只有一个最小质因子,所以每个数只会被筛一次,所以是线性的。

//朴素筛法
#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++] = i;
        }
        for(int j = i + i; j <= n; j += i) st[j] = true;
    }
}

int main()
{
    int n;
    scanf("%d", &n);

    get_primes(n);

    printf("%d\n", cnt);

    return 0;
}

//由于只有质数的倍数才需要筛掉,所以可以将筛选的循环放到判断里面去

//埃氏筛法
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;
        }
    }
}

//埃氏筛法是筛掉质数的倍数,但仍会重复计算,线性筛法中每个合数只会被其最小质因子筛掉,解决了重复计算的问题

//线性筛法
void get_primes(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;
        }
    }
}
posted @   恺雯  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示