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. 约数之和(唯一分解定理+组合数)的主要内容,如果未能解决你的问题,请参考以下文章