约数和定理

约数和定理

定理

对于一个大于1的正整数n可以分解质因数: n = p 1 α 1 ∗ p 2 α 2 ∗ ⋯ p k α k n=p_1^{\alpha _1}*p_2^{\alpha _2}*\cdots p_k^{\alpha _k} n=p1α1p2α2pkαk,由约数个数定理可知,n的正约数的个数有 ( α 1 + 1 ) ( α 2 + 1 ) ⋯ ( α k + 1 ) (\alpha_1 +1)(\alpha _2+1)\cdots (\alpha_k+1) (α1+1)(α2+1)(αk+1)个。

那么n的 ( α 1 + 1 ) ( α 2 + 1 ) ⋯ ( α k + 1 ) (\alpha_1+1)(\alpha_2+1)\cdots (\alpha_k +1) (α1+1)(α2+1)(αk+1)个正约数的和为: f ( n ) = ( p 1 0 + p 1 1 + ⋯ + p 1 α 1 ) ( p 2 0 + p 2 1 + ⋯ + p 2 α 2 ) ⋯ ( p k 0 + p k 1 + ⋯ + p k α k ) f(n)=(p_1^0+p_1^1+\cdots+p_1^{\alpha_1})(p_2^0+p_2^1+\cdots +p_2^{\alpha_2})\cdots (p_k^0+p_k^1+\cdots +p_k^{\alpha _k}) f(n)=(p10+p11++p1α1)(p20+p21++p2α2)(pk0+pk1++pkαk)


证明

若n可以分解质因数: n = p 1 α 1 ∗ p 2 α 2 ∗ ⋯ p k α k n=p_1^{\alpha_1}*p_2^{\alpha _2}*\cdots p_k^{\alpha_k} n=p1α1p2α2pkαk,可知 p 1 α 1 p_1^{\alpha_1} p1α1的约数有: p 1 0 、 p 1 1 ⋯ p 1 α 1 p_1^0、p_1^1\cdots p_1^{\alpha _1} p10p11p1α1 ⋯ \cdots ,同理可知, p k α k p_k^{\alpha _k} pkαk的约数有: p k 0 、 p k 1 、 ⋯ p k α k p_k^0、p_k^1、\cdots p_k^{\alpha_k} pk0pk1pkαk。实际上n的约数就是在 p 1 α 1 p_1^{\alpha _1} p1α1 p 2 α 2 p_2^{\alpha _2} p2α2 ⋯ \cdots p k α k p_k^{\alpha _k} pkαk每一个的约数中 分别随便挑出一个因子来相乘而得到的。由乘法原理可知它们的和为: f ( n ) = ( p 1 0 + p 1 1 + p 1 2 + ⋯ + p 1 α 1 ) ( p 2 0 + p 2 1 + ⋯ + p 2 α 2 ) ⋯ ( p k 0 + p k 1 + ⋯ + p k α k ) f(n)=(p_1^0+p_1^1+p_1^2+\cdots +p_1^{\alpha _1})(p_2^0+p_2^1+\cdots +p_2^{\alpha_2})\cdots (p_k^0+p_k^1+\cdots +p_k^{\alpha _k}) f(n)=(p10+p11+p12++p1α1)(p20+p21++p2α2)(pk0+pk1++pkαk)


例题

正整数360的所有正约数的和是多少?

解:将360分解质因数可得

360= 2 3 ∗ 3 2 ∗ 5 1 2^3*3^2*5^1 233251;

由约数和定理可知,360所有正约数的和为

( 2 0 + 2 1 + 2 2 + 2 3 ) ( 3 0 + 3 1 + 3 2 ) ( 5 0 + 5 1 ) = ( 1 + 2 + 4 + 8 ) ( 1 + 3 + 9 ) ( 1 + 5 ) = 1170 (2^0+2^1+2^2+2^3)(3^0+3^1+3^2)(5^0+5^1)=(1+2+4+8)(1+3+9)(1+5)=1170 (20+21+22+23)(30+31+32)(50+51)=(1+2+4+8)(1+3+9)(1+5)=1170

可知360的约数有1、2、3、4、5、6、8、9、10、12、15、18、20、24、30、36、40、45、60、72、90、120、180、360;则约数之和为

1+2+3+4+5+6+8+9+10+12+15+18+20+24+30+36+40+45+60+72+90+120+180+360=1170。


题目描述

约数和定理_第1张图片


核心思路

这一题可以用约数和定理来求解。


代码

#include
#include
using namespace std;
const int mod = 1e9 + 7;
typedef long long LL;
int main()
{
    int n;
    cin >> n;
    unordered_mapprimes;
    while (n--)
    {
        int x;
        cin >> x;
        //将每一个整数x都分解质因数
        for (int i = 2; i <= x / i; i++)
        {
            while (x % i == 0)
            {
                primes[i]++;
                x /= i;
            }
        }
        if (x > 1)
            primes[x]++;
    }
    LL res = 1;
    //运用 约数和定理 来求解答案
    for (auto it : primes)
    {
        LL p = it.first, a = it.second;//p是底数 a是指数
        LL t = 1;
        while (a--)
            t = (t * p + 1) % mod;//这里也取模是防止溢出,确保中间结果不会溢出。
        res = res * t % mod;
    }
    cout << res << endl;
    return 0;
}

你可能感兴趣的:(算法)