约数和问题
问题链接:https://ac.nowcoder.com/acm/contest/998/F
题意:求ab的所有约数的和。
知识点:数学(质因数分解、唯一分解定理、约数和公式)、分治递归。
相关介绍:
- 唯一分解定理:每个大于1的自然数n均可分解为有限个素数之积,如不计素数在乘积中的顺序,那么这种分解方式是唯一的。并且n可以唯一写成p1a1p2a2p3a3……pnan
- 质因数分解:我们可以保证当n被升序的每一个数除到不能除时,其因数都是质数,具体证明见线性筛。
- 约数个数公式:由①中记法,我们记N为约数的个数,以p1a1为例,其p10……p1a1都是n的约数,于是就有a1+1个,同时根据乘法原理,则N = (a1 + 1)(a2 + 1)(a3 + 1)……(an + 1)
- 约数和公式:由③,我们相当于是做个一个排列,而对于每种情况,都是只取其中一种,不难发现,记S为所有约数之和,则S = (p10 + p11 + …… + p1a1)……(pn0 + pn1 + …… + pnan)
- 由于是求的ab的约数之和,我们不妨先将a记作①中形式,那么对于①中的每个p,其指数都为a1*b。
思路:
- 相关知识点都已经给出,我们的思路也不难得到,那就是通过分解a的质因数,然后求所有的质因数(注意加了b次方)之和。
- 注意在求解约数和时,我们采取的是一种递归的方法,因为我们可以做以下推导,得到递归思路,进而避免了不必要的计算。
- S(p,k) = p0 + p1 + …… + pk,其中p代表质因数,k代表其最高次方
- 当k为奇数时,S(p,k) = p0 + p1 + …… + pk = p0 + p1 + …… + pk/2 - 1 + pk/2 + …… + pk = p0 + p1 + …… + pk/2 - 1 + pk/2(p0 + p1 + …… + pk/2 - 1) + pk = (1 + pk/2)S(p, k / 2)+ pk
- 当k为偶数时,也一样的推。
总结:
- 千万要注意运算符的优先级,k & 1 == 1与 (k & 1)== 1是不一样的!!!
代码:
#include <bits/stdc++.h>
using namespace std;
const int mod = 9901;
int qpow(int a, int b)
{
int res = 1;
a %= mod;
while(b)
{
if(b & 1) res = res % mod * a % mod;
a = a % mod * a % mod;
b >>= 1;
}
return res % mod;
}
int sum(int p, int k)
{
if(k == 0) return 1;
else if(k % 2 == 0)
return ((1 + qpow(p, k >> 1)) * sum(p, (k >> 1) - 1) + qpow(p, k)) % mod;
else
return ((1 + qpow(p, (k + 1) >> 1)) * sum(p, (k - 1) >> 1)) % mod;
}
int main()
{
ios::sync_with_stdio(false);
int a, b; cin >> a >> b;
int ans = 1;
for(int i = 2; i <= a; i++)
{
int s = 0;
while(a % i == 0)
{
s++;
a /= i;
}
if(s) ans = ans * sum(i, s * b) % mod;
}
if(a == 0)
cout << 0 << endl;
else
cout << ans << endl;
return 0;
}


浙公网安备 33010602011771号