质数与约数

质数与约数

质数

质数和合数的概念只针对于大于1的整数成立。

质数:在大于1的整数中,如果只包含1和本身这两个约数,就被称为质数,或者素数。

质数的判定

试除法

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

d|n>nd|n(a|bab)3|12>4|122|12>6|12

因此在枚举的过程中,我们可以只枚举较小的那个数,即dnd,d2n,dn

试除法判定质数算法模板

O(n)

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

分解质因数

试除法

从小到大枚举所有的数,判断是否能被整除从而枚举所有质因数O(n)

void divide(int n)
{
    for(int i = 2; i <= n; i ++)
    {
    	if(n % i == 0)
        {
            int s = 0;
            while(n % i == 0)
            {
                n /= i;
                s ++;
            }
            printf("%d %d\n", i, s);
        }
    }
}

n中最多只包含一个大于n的质因子(假如有两个大于n的质因子,乘起来就会大于n)

因此只需要枚举2到n,在判断最后剩下来的数是否为1,不为1说明是大于n的质因子并输出,优化为O(n)

试除法分解质因数算法模板

void divide(int x)
{
    for (int i = 2; i <= x / i; i ++ )
        if (x % i == 0)		// i 一定是质数
        {
            int s = 0;
            while (x % i == 0) x /= i, s ++ ;
            printf("%d %d\n", i, s);
        }
    if (x > 1) printf("%d 1\n", x);
    cout << endl;
}

筛法

朴素筛法

i=2时,循环n2

i=3时,循环3n

n2+n3+...+nn=n(12+13+...+1n)1+12+13+...+1n=lnn+cn2+n3+...+nn=nlnn<nlogn

O(nlogn)

朴素筛法求素数算法模板

int primes[N], cnt;     // primes[]存储所有素数
bool st[N];         // st[x]存储x是否被筛掉,m

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; 
    }
}

埃氏筛法

如果我们留下了p,说明p是一个质数。

对于合数来说,它的倍数也一定被这个合数的因此筛掉了,所有不用再考虑筛合数的倍数

我们可以只删所有质数的倍数,对于非质数,我们不需要删他的倍数

质数定理1n中有nlnn个质数

优化为O(nloglogn)

埃氏筛法求素数算法模板

int primes[N], cnt;     // primes[]存储所有素数
bool st[N];         // st[x]存储x是否被筛掉

void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (st[i]) continue;
        primes[cnt ++ ] = i;
        for (int j = i + i; j <= n; j += i)
            st[j] = true;
    }
}

欧拉(线性)筛法

每个数n只会被最小质因子筛掉

循环里面有两种情况:

  1. i%primes[j]==0primes[j]一定是i的最小质因子,primes[j]一定是primes[j]×i的最小质因子
  2. i%primes[j]!=0primes[j]一定小于i的所有最小质因子,primes[j]也一定是primes[j]×i的最小质因子

对于一个合数x,假设primes[j]x的最小质因子,当i枚举到x/primes[j]的时候,就会被筛掉

所以,每个数只会被他的最小质因子筛掉,只会被筛一次

可以通过算术基本定理来理解

O(n)

线性筛法求素数算法模板

int primes[N], cnt;     // primes[]存储所有素数
bool st[N];         // st[x]存储x是否被筛掉

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;		// primes[j]一定是i的最小质因子
        }
    }
}

约数

试除法求约数

试除法求所有约数算法模板

vector<int> get_divisors(int x)
{
    vector<int> res;
    for (int i = 1; i <= x / i; i ++ )
        if (x % i == 0)
        {
            res.push_back(i);
            if (i != x / i) res.push_back(x / i);
        }
    sort(res.begin(), res.end());
    return res;
}

约数个数

基于算术基本定理

N=p1α1×p2α2×...×pnαn:(α1+1)×(α2+1)×...×(αn+1):mNN=p1α1×p2α2×...×pnαnm=p1β1×p2β2×...×pnβn(βi0,1,...,αi)β1α1+1...,βnαn+1m(α1+1)×(α2+1)×...×(αn+1)

约数之和

N=p1α1×p2α2×...×pnαn:(p10+p11+...p1α1)×...×(pk0+pk1+...pkαk)()

72=23×32:(3+1)×(2+1)=121,2,4,81,3,96,12,18,24,36,721×(1+31+32)+2×(1+31+32)+22×(1+31+32)+23×(1+31+32)=(1+2+22+23)×(1+3+32)

约数个数和约数之和算法模板

如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)
    
// 质因数分解,存储在map中
void divide(int n)
{
    for(int i = 2; i <= n / i; i ++)
    {
        if(n % i == 0)
        {
            int s = 0;
            while(n % i == 0)	n /= i, s ++;
            mp[i] += s;
        }
    }
    if(n != 1)  mp[n] ++;
}

// 约数个数
for(auto p : mp)
{
    ans = (ans * (p.second + 1) % mod) % mod;
}

// 约数之和
for(auto p : mp)
{
    long long num = 1;
    for(int i = 0; i < p.second; i ++)
    {
        num = (num * p.first + 1) % mod;
    }
    ans = (ans * (num % mod)) % mod;
}

欧几里得算法

d|a,d|bd|a+b,d|ax+bya%b=aabb=acb(a,b)=(b,a%b)=(b,acb)

欧几里得算法算法模板

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}
posted @   钰见梵星  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示