AcWing 871. 约数之和(唯一分解定理+组合数)

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 871. 约数之和(唯一分解定理+组合数)相关的知识,希望对你有一定的参考价值。

题目连接

https://www.acwing.com/problem/content/description/873/

思路

如果n可以写成 f ( n ) = a 1 α 1 × a 2 α 2 … … × a k α k f(n)=a_1^α_1\\times a_2^α_2……\\times a_k^α_k f(n)=a1α1×a2α2×akαk a 1 , a 2 , … … , a k a_1,a_2,……,a_k a1,a2,,ak均为质数)
那么n的约数的和为:
s u m = ( a 1 0 + a 1 1 + a 1 2 + … … a 1 α 1 ) × ( a 2 0 + a 2 1 + a 2 2 + … … a 2 α 2 ) × … … × ( a k 0 + a k 1 + a k 2 + … … a k α k ) sum = (a_1^0 + a_1^1+a_1^2+……a_1^α_1)\\times (a_2^0 + a_2^1+a_2^2+……a_2^α_2)\\times …… \\times (a_k^0 + a_k^1+a_k^2+……a_k^α_k) sum=(a10+a11+a12+a1α1)×(a20+a21+a22+a2α2)××(ak0+ak1+ak2+akαk)
所以我们直接将每一个因子唯一分解后将数量统计出来,最后然后遍历将每个质因子的贡献通过求和公式算出并累乘即可,详情请看吗代码

代码

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define ll long long
#define int long long
map<ll,ll> vis;
ll n,a;
void slove()
    for(ll i = 2;i * i <= a; ++i) 
        while(a % i == 0) vis[i]++,a /= i;
    
    if(a-1) vis[a]++;


ll ksm(ll a,ll b)
    ll ans = 1;
    while(b)
        if(b & 1) ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    
    return ans;


ll inv(ll x) return ksm(x,mod-2);

signed main()

    scanf("%lld",&n);
    for(ll i = 1;i <= n; ++i) 
        scanf("%lld",&a);
        slove();
    
    long long ans = 1LL;
    for(auto it : vis)  
        ll q = it.first;
        ll k = it.second;
        ll res = 0;
        if(q == 1) 
            res = n + 1;
        else 
            res = ((ksm(q,k + 1) - 1LL + mod) * inv(q-1)) % mod;
        
        ans = (ans * res) % mod;
    
    printf("%lld\\n",ans);

    return 0;

以上是关于AcWing 871. 约数之和(唯一分解定理+组合数)的主要内容,如果未能解决你的问题,请参考以下文章

871. 约数之和

AcWing 870. 约数个数(唯一分解+组合数)

UVA294DIvisors(唯一分解定理+约数个数)

AcWing - 97 - 约数之和(分治因数和)

A^B的约数(因子)之和对MOD取模

阶乘约数——蓝桥杯python组国赛题(C++唯一分解定理)