信息学奥赛中的数学知识——约数

约数个数

任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积:
N = p 1 a 1 × p 2 a 2 × p 3 a 3 . . . p n a n N=p_1^{a_1}×p_2^{a_2}× p_3^{a_3} ... p_n^{a_n} N=p1a1×p2a2×p3a3...pnan这里 p 1 < p 2 < p 3 . . . < p n p_1 < p_2 < p_3... < p_n p1<p2<p3...<pn均为质数,其中指数 a i a_i ai是正整数。这样的分解称为 N 的标准分解式。

N 的约数个数 = ( a 1 + 1 ) × ( a 2 + 1 ) × ( a 3 + 1 ) × . . . × ( a n + 1 ) (a_1+1) × (a_2 + 1) × (a_3 +1) × ... × (a_n + 1) (a1+1)×(a2+1)×(a3+1)×...×(an+1)

证明

N N N可以分解质因数:
N = p 1 a 1 × p 2 a 2 × p 3 a 3 . . . p n a n N=p_1^{a_1}×p_2^{a_2}× p_3^{a_3} ... p_n^{a_n} N=p1a1×p2a2×p3a3...pnan
p 1 a 1 p_1^{a_1} p1a1由约数定义可知的约数有: p 1 0 , p 1 1 , . . . p 1 a 1 p_1^0,p_1^1,...p_1^{a_1} p10,p11,...p1a1,共 ( a 1 + 1 ) (a_1+1) (a1+1)个;同理 p 2 a 2 p_2^{a_2} p2a2的约数有 ( a 2 + 1 ) (a_2+1) (a2+1)个;……; p k a k p_k^{a_k} pkak的约数有 ( a k + 1 ) (a_k+1) (ak+1)个。

故根据乘法原理: N N N的约数的个数就是: ( a 1 + 1 ) × ( a 2 + 1 ) × . . . × ( a n + 1 ) (a_1+1)\times(a_2+1)\times...\times(a_n+1) (a1+1)×(a2+1)×...×(an+1)

模板问题

给定 n n n 个正整数 a i a_i ai,请你输出这些数的乘积的约数个数,答案对 1 0 9 + 7 10^9+7 109+7 取模。

输入格式

第一行包含整数 n n n
接下来 n n n 行,每行包含一个整数 a i a_i ai

输出格式

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

数据范围
1 ≤ n ≤ 100 1≤n≤100 1n100,
1 ≤ a i ≤ 2 × 1 0 9 1≤a_i≤2×10^9 1ai2×109

输入样例

3
2
6
8

输出样例

12

代码实现

#include <iostream>
#include <map>
using namespace std;

/*
如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
*/
const int mod = 1e9 + 7;
typedef long long LL;
int main()
{
    int n;
    cin >>  n;
    map<int, int> h;
    while(n --)
    {
        int x;
        cin >> x;
        for(int i = 2; i <= x / i; i ++)
        {
            while(x % i == 0)
            {
                h[i] ++;
                x /= i;
            }
        }
        // 任何一个数字x,最多只包含一个大于sqrt(x)的质因子
        if(x > 1) h[x] ++;
    }

    int res = 1;
    for(map<int, int>::iterator it = h.begin(); it != h.end(); it ++)
    {
        res = (LL) res * (it -> second + 1) % mod;
    }
    cout << res << endl;
    return 0;
}

约数之和

N 的约数之和 = ( p 1 0 + p 1 1 + p 1 2 + . . . + p 1 a 1 ) × ( p 2 0 + p 2 1 + p 2 2 + . . . + p 2 a 2 ) × . . . × ( p n 0 + p n 1 + p n 2 + . . . + p n a n ) (p_1^0+p_1^1+p_1^2+...+ p_1^{a_1}) × (p_2^0 + p_2^1 + p_2^2 + ... +p_2^{a_2})×... × (p_n^0 + p_n^1 + p_n^2 + ... + p_n^{a_n}) (p10+p11+p12+...+p1a1)×(p20+p21+p22+...+p2a2)×...×(pn0+pn1+pn2+...+pnan)

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
//divs[i] = j 表示因子i的个数为j
unordered_map<int, int> divs;

int main(){
    int n;
    cin>>n;
    while(n--){
        int x; cin>>x;
        //求x的约数,及其个数
        for(int i = 2; i <= x / i; i++){
            while(x % i == 0) {
                divs[i]++;
                x /= i;
            }
        }
        if(x > 1) divs[x]++;

    }
    long long res = 1;
    for(auto d : divs){
        int p = d.first, a = d.second;

        long long t = 1;
        // t[1] = 1 + p^1
        // t[2] = 1 + (1 + p) * p  = 1 + p^1 + p^2
        // t[k - 1] = 1 + p^1 + p^2 + ... + p^{k-1}
        // t[k] = 1 + t[k-1] * p= 1 + ( 1 + p^1 + p^2 + p^{k-1}) * p = 1 + p^1 + p^2 +...+ p^{k-1} + p^k
        while(a--) 
            t = (1 + t * p) % mod; 

        res = res * t % mod;

    }
    cout<<res<<endl;

    return 0;
}

信息学奥赛一本通题解》目录 alex 一、引言 1. 欢迎词 2. 关于《信息学奥赛一本通题解》 3. 题解使用方法说明 二、初级篇 1. 基本数据结构 a. 数组 b. 链表 c. 栈和队列 2. 基本算法 a. 排序算法 b. 查找算法 c. 递归与分治 3. 动态规划入门 a. 线性动态规划 b. 背包问题 c. 最长公共子序列 4. 图论算法初步 a. 图的表示与遍历 b. 最短路径算法 c. 最小生成树算法 三、级篇 1. 树与图算法 a. 树的遍历与构建 b. 树的深度优先搜索与广度优先搜索 c. 图的深度优先搜索与广度优先搜索 d. 带权图的最短路径算法 2. 数据结构进阶 a. 堆与堆排序 b. 并查集 c. 线段树 3. 动态规划提高 a. 状态压缩动态规划 b. 概率与期望 c. 区间动态规划 4. 数论与计算几何 a. 素数与公约数 b. 快速幂与模拟退火 c. 凸包与最近对问题 四、高级篇 1. 字符串算法 a. 字符串匹配算法 b. 后缀数组 c. AC自动机 2. 图论算法深入 a. 强连通分量 b. 拓扑排序与关键路径 c. 二分图匹配 3. 数据结构高级应用 a. 平衡树 b. 字典树 c. 哈希表 4. 数论与计算几何进阶 a. 组合数学 b. 线性规划与网络流 c. 几何算法的应用 五、附录 1. 常用数学公式 2. 常见算法时间复杂度与空间复杂度 3. 常见数据结构操作复杂度分析 六、参考文献 1. 专业技术书籍推荐 2. 网络资源推荐 通过这本《信息学奥赛一本通题解》,读者可以系统地学习和掌握信息学竞赛常见的算法、数据结构以及相关问题的解法。本书旨在提供一份全面而深入的题解和算法思路,帮助读者培养良好的编程思维和解决问题的能力。无论是初级还是高级选手,都可以从本书获得有效的学习资源和指导。祝愿读者在信息学奥赛的道路上取得优异的成绩!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少儿编程乔老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值