数学知识1.2-约数

一、简述

本文章主要介绍有关约数的基础算法。

二、约数

约数,又称因数。整数 a 除以整数 b(b ≠ 0) 除得的商正好是整数而没有余数,我们就说 a 能被 b 整除,或 b 能整除 aa 称为 b 的倍数,b 称为 a 的约数。

三、试除法求约数

设一个数 n,则我们只需从1遍历到 n,把所有的整除 n 的数就是 n 的约数。
参考试除法判断质数,如果对于一个数 n,若存在 d | n(d 整除 n),则 dn | n,基于此,我们可以对上面的算法进行优化,使得时间复杂度降到 O(n)

模板题AcWing869.试除法求约数

题目描述

给定 n 个正整数 ai,请你按照从小到大的顺序输出它的所有约数。

输入格式

第一行包含整数 n
接下来 n 行,每行包含一个正整数 ai

输出格式

n 行,其中第 i 行输出第 i 个整数 ai 的所有约数。

数据范围

1≤ n ≤100,2≤ ai ≤210

输入样例
2
6
8
输出样例
1 2 3 6
1 2 4 8
解题思路

试除法,并且对于平方数此类的数,我们要对它的约数进行去重,这里我们可以采用 set,同时 set 也可以实现自动排序,无需我们再对存放约数的数组进行排序。

C++代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;

set<int> get_divisors(int x)
{
    set<int> res;
    for(int i = 1; i <= x / i; i ++)
    {
        if(x % i == 0)
        {
            res.insert(i);
            res.insert(x / i);
        }
    }
    return res;
}

int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++)
    {
        int x;
        cin >> x;
        set<int> t = get_divisors(x);
        for(auto v : t)
            cout << v << ' ';
        cout << endl;
    }
    return 0;
}

四、约数个数

  • 算术基本定理:任何一个大于1的自然数 N,都可以唯一分解成有限个质数的乘积。
    N = P1a1P2a2P3a3⋅⋅⋅Pnan,这里 P1 < P2 < ⋅⋅⋅ < Pn 且均为质数,其指数均是正整数。
  • 约数个数 = (a1 + 1) * (a2 + 1) * ... * (an + 1)。

模板题AcWing870. 约数个数

题目描述

给定 n 个正整数 ai,请你输出这些数的乘积的约数个数,答案对 109+7 取模。

输入格式

第一行包含整数 n
接下来 n 行,每行包含一个正整数 ai

输出格式

输出一个整数,表示所给正整数的乘积的约数个数,答案需对 109+7 取模。

数据范围

1≤ n ≤100,2≤ ai ≤2×109

输入样例
3
2
6
8
输出样例
12
解题思路

试除法,因为我们要利用对应质因数的指数,我们使用哈希表存储。

C++代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N = 110, MOD = 1e9 + 7;
typedef long long LL;

int n;
unordered_map<int, int> primes;

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i ++)
    {
        int x;
        cin >> x;
        for(int j = 2; j <= x / j; j ++)
        {
            while(x % j == 0)
            {
                x /= j;
                primes[j] ++;
            }
        }
        if(x > 1) primes[x] ++;
    }
    LL res = 1;
    for(auto [k, v] : primes)
    {
        res = (res * (v + 1)) % MOD;
    }
    cout << res;
    return 0;
}

五、约数之和

约数之和的依据也是算术基本定理。
约数之和 = (P10 + P12 + ... + P1a1) * (P20 + P22 + ... + P2a1) * ... * (Pn0 + Pn2 + ... + Pna1)。

模板题AcWing871.约数之和

题目描述

给定 n 个正整数 ai,请你输出这些数的乘积的约数之和,答案对 109+7 取模。

输入格式

共一行,包含整数 n
接下来 n 行,每行包含一个整数 ai

输出格式

输出一个整数,表示所给正整数的乘积的约数之和,答案需对 109+7 取模。

数据范围

1≤ n ≤106

输入样例
3
2
6
8
输出样例
252
解题思路

参考前面试除法计算约数个数,我们利用哈希表存储质因数及其指数之后,对质因数 Pi 及其指数 ai 计算 Pi0 + Pi2 + ... + Piai,将所有的结果累乘即可。

C++代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N = 110, MOD = 1e9 + 7;
typedef long long LL;

int n;
unordered_map<int, int> primes;

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i ++)
    {
        int x;
        cin >> x;
        for(int j = 2; j <= x / j; j ++)
        {
            while(x % j == 0)
            {
                x /= j;
                primes[j] ++;
            }
        }
        if(x > 1) primes[x] ++;
    }
    LL res = 1;
    for(auto [k, v] : primes)
    {
        LL t = 1;
        int p = k, a = v;
        while(a --)
        {
            t = (t * p + 1) % MOD;
        }
        res = (res * t) % MOD;
    }
    cout << res;
    return 0;
}

六、最大公约数

计算两个数的最大公约数我们常使用的算法是辗转相除法(欧几里得算法)。
核心思想:如果 d | ad | b,则 d | xa+yb,这里 xy 都是整数。
欧几里得算法的表示:(ab) = (ba mod b),mod 是求余操作,等号表示左右的最大公约数相等。
证明:首先 a mod b = a - abb = a - cb,这里 ab 是整除,设最大公约数是 d

  • 左->右:d | ad | b,则 d | bd | acb,等号成立。
  • 右->左:d | bd | acb,则d | acb+cb 也就是 d | ad | b,等号成立。
    证毕。

模板题AcWing872.最大公约数

题目描述

给定 n 对正整数 aibi,请你求出每对数的最大公约数。

输入格式

共一行,包含整数 n
接下来 n 行,每行一对正整数 aibi

输出格式

输出共 n 行,每行输出一个整数对的最大公约数。

数据范围

1≤ n ≤ 105
1≤ aibi ≤ 2×109

输入样例
2
3 6
4 6
输出样例
3
2
解题思路

辗转相除法。

C++代码
#include <iostream>
using namespace std;

int gcd(int a, int b)
{
    if(a % b == 0) return b;
    return gcd(b, a % b);
}

int n;

int main()
{
    cin >> n;
    while(n --)
    {
        int a, b;
        cin >> a >> b;
        printf("%d\n", gcd(a, b));
    }
    return 0;
}
posted @   Cocoicobird  阅读(77)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示