约数之和

题目描述

假设现在有两个自然数 A 和 B,S 是 A B A^B AB 的所有约数之和。

请你求出 S mod 9901的值是多少。

输入格式

在一行中输入用空格隔开的两个整数 A 和 B 。

输出格式

输出一个整数,代表 S mod 9901 的值。

数据范围

0 ≤ A , B ≤ 5 × 1 0 7 0≤A,B≤5\times10^7 0A,B5×107

输入样例:

2 3

输出样例:

15

解题思路

本题目需要知道一定的数学知识。

假定 A B = ( p 1 t 1 × p 2 t 2 × … … × p n t n ) B = p 1 t 1 B × p 2 t 2 B × … … × p n t n B = p 1 k 1 × p 2 k 2 × … … × p n k n ( k i = t i B ; p i ∈ 质 数 ) A^B = (p_1^{t_1} \times p_2^{t_2} \times …… \times p_n^{t_n})^B = p_1^{t_1B} \times p_2^{t_2B} \times …… \times p_n^{t_nB} = p_1^{k_1} \times p_2^{k_2} \times …… \times p_n^{k_n} (k_i = t_iB ; p_i \in 质数) AB=(p1t1×p2t2××pntn)B=p1t1B×p2t2B××pntnB=p1k1×p2k2××pnkn(ki=tiB;pi)

A 的约数(因子)一定是若干 p i p_i pi 的任意搭配。因此可以得知,约数数量为 ( k 1 + 1 ) × ( k 2 + 1 ) × … … × ( k n + 1 ) (k_1 + 1) \times (k_2 + 1) \times ……\times (k_n + 1) (k1+1)×(k2+1)××(kn+1)

所有约数之和为 ( p 1 0 + p 1 1 + … … + p 1 k 1 ) × ( p 2 0 + p 2 1 + … … + p 2 k 2 ) × … … × ( p n 0 + p n 1 + … … + p n k n ) (p_1^0 + p_1^1 + …… + p_1^{k_1}) \times (p_2^0 + p_2^1 + …… + p_2^{k_2}) \times …… \times (p_n^0 + p_n^1 + …… + p_n^{k_n}) (p10+p11++p1k1)×(p20+p21++p2k2)××(pn0+pn1++pnkn)

那么现在问题就是如何求解 s u m ( p 1 , k ) = p 1 0 + p 1 1 + … … + p 1 k 1 sum(p_1,k) = p_1^0 + p_1^1 + …… + p_1^{k_1} sum(p1,k)=p10+p11++p1k1

一种方式是直接使用等比数列求和公式。另外一种方式则是使用递归进行解决。

这里介绍一下如何进行递归解决。

当 k 为奇数时,总共有偶数项求和。

s u m ( p 1 , k ) = p 1 0 + p 1 1 + … … + p 1 k 1 = p 1 0 + p 1 1 + … … + p 1 k / 2 + p 1 k / 2 + 1 + … … + p 1 k sum(p_1,k) = p_1^0 + p_1^1 + …… + p_1^{k_1} = p_1^0 + p_1^1 + …… + p_1^{k/2} + p_1^{k/2 + 1} + …… + p_1^k sum(p1,k)=p10+p11++p1k1=p10+p11++p1k/2+p1k/2+1++p1k

= p 1 0 + p 1 1 + … … + p 1 k / 2 + p 1 k / 2 + 1 ( p 1 0 + … … + p 1 k / 2 ) = p_1^0 + p_1^1 + …… + p_1^{k/2} + p_1^{k/2 + 1}(p_1^0 + …… + p_1^{k/2}) =p10+p11++p1k/2+p1k/2+1(p10++p1k/2)

= ( p 1 0 + p 1 1 + … … + p 1 k / 2 ) × ( 1 + p 1 k / 2 + 1 ) = (p_1^0 + p_1^1 + …… + p_1^{k/2}) \times (1 + p_1^{k/2 + 1}) =(p10+p11++p1k/2)×(1+p1k/2+1)

这样就出现了递归。

当 k 为偶数时,总共有奇数项。

s u m ( p 1 , k ) = p 1 0 + p 1 1 + … … + p 1 k 1 = 1 + p 1 ( p 1 0 + p 1 1 + … … + p 1 k − 1 ) sum(p_1,k) = p_1^0 + p_1^1 + …… + p_1^{k_1} = 1 + p_1(p_1^0 + p_1^1 + …… + p_1^{k - 1}) sum(p1,k)=p10+p11++p1k1=1+p1(p10+p11++p1k1)

这样就将奇数项转换为了偶数项。

#include <iostream>
using namespace std;

const int mod = 9901;

// 快速幂乘求解 (x^k)%p
int quickmul(int x,int k,int p)
{
    x = x % mod;
    int res = 1,t = x;
    while(k)
    {
        if(k & 1)
        {
            res = (res * t) % p;
        }
        k = k >> 1;
        t = (t * t) % p;
    }
    return res;
}


int sum(int p,int k)
{
    if(k == 0)
    {
        return 1;
    }
    
    if(k & 1)
    {
        return ((1 + quickmul(p,k / 2 + 1,mod)) * sum(p,k / 2)) % mod;
    }
    else
    {
        return (1 + p % mod * sum(p,k - 1)) % mod;
    }
}

int main()
{
    int A,B;
    int s,result = 1;
    cin >> A >> B;
    
    for(int i = 2;i <= A;i++)
    {
        s = 0;
        while(A % i == 0)
        {
            s++;
            A = A / i;
        }
        if(s)
        {
            result = result * sum(i,s * B) % mod;
        }
    }
    
    // 题目中说A,B不会同时为0,B是否为0,sum函数都可以解决,但是A为0需要单独说明
    if(!A)
    {
        result = 0;
    }
    cout << result << endl;
    
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值