约数和问题

问题链接:https://ac.nowcoder.com/acm/contest/998/F

题意:求ab的所有约数的和。

知识点:数学(质因数分解、唯一分解定理、约数和公式)、分治递归。

相关介绍:

  1. 唯一分解定理:每个大于1的自然数n均可分解为有限个素数之积,如不计素数在乘积中的顺序,那么这种分解方式是唯一的。并且n可以唯一写成p1a1p2a2p3a3……pnan
  2. 质因数分解:我们可以保证当n被升序的每一个数除到不能除时,其因数都是质数,具体证明见线性筛。
  3. 约数个数公式:由①中记法,我们记N为约数的个数,以p1a1为例,其p10……p1a1都是n的约数,于是就有a1+1个,同时根据乘法原理,则N = (a1 + 1)(a2 + 1)(a3 + 1)……(an + 1)
  4. 约数和公式:由③,我们相当于是做个一个排列,而对于每种情况,都是只取其中一种,不难发现,记S为所有约数之和,则S = (p10 + p11 + …… + p1a1)……(pn0  + pn1 + …… + pnan
  5. 由于是求的ab的约数之和,我们不妨先将a记作①中形式,那么对于①中的每个p,其指数都为a1*b。

思路:

  1. 相关知识点都已经给出,我们的思路也不难得到,那就是通过分解a的质因数,然后求所有的质因数(注意加了b次方)之和。
  2. 注意在求解约数和时,我们采取的是一种递归的方法,因为我们可以做以下推导,得到递归思路,进而避免了不必要的计算。
  3. S(p,k) = p0 + p1 + …… + pk,其中p代表质因数,k代表其最高次方
  4. 当k为奇数时,S(p,k) = p0 + p1 + …… + pkp0 + p1 + …… + pk/2 - 1 + pk/2 + …… + pkp0 + p1 + …… + pk/2 - 1 + pk/2(p0 + p1 + …… + pk/2 - 1)  + pk = (1 + pk/2)S(p, k / 2)+ pk
  5. 当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;
}

  

 

posted @ 2020-07-20 00:49  ACM-Epoch  阅读(461)  评论(0编辑  收藏  举报