AcWing_97 约数之和

该博客详细介绍了如何解决AcWing上97题的约数之和问题,包括题目的描述、输入输出格式、数据范围以及样例。博主分享了利用数论知识和分治法来求解S mod 9901的值,特别强调了不能直接使用等比数列求和公式,需要避免除法操作,并给出了当质因数幂次为奇偶时的求和方法。

约数之和

链接

AcWing_97 约数之和

题目描述

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

请你求出 S   m o d   9901 S\bmod9901 Smod9901 的值是多少。

输入格式

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

输出格式

输出一个整数,代表 S   m o d   9901 S\bmod9901 Smod9901 的值。

数据范围

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

输入样例

2 3

输出样例

15

注意

A A A B B B 不会同时为 0 0 0

思路

由数论的知识可知,若将 A A A 分解质因数,可以表示为:
A = p 1 c 1 ∗ p 2 c 2 ∗ p 3 c 3 ∗ . . . ∗ p n c n A=p_1^{c_1}*p_2^{c_2}*p_3^{c_3}*...*p_n^{c_n} A=p1c1p2c2p3c3...pncn

那么, A B A^B AB 的约数之和则可以表示为:
( p 1 0 + p 1 1 + p 1 2 + . . . . . . p 1 c 1 ) ∗ . . . . . . ∗ ( p n 0 + p n 1 + p n 2 + ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ p n c n ) = ∏ i = 1 n ( ∑ j = 0 c i p i j ) (p_1^0+p_1^1+p_1^2+......p_1^{c_1})*......*(p_n^0+p_n^1+p_n^2+······p_n^{c_n})=\prod _{i=1}^{n}\left(\sum _{j=0}^{c_i}p_i^j\right) (p10+p11+p12+......p1c

在计算一个正整数的所有约数之和时,可以使用数论中的公式:如果一个正整数 $ X $ 的质因数分解形式为 $ X = p_1^{a_1} p_2^{a_2} \cdots p_k^{a_k} $,那么 $ X $ 的所有正约数之和 $ S $ 可以通过以下公式计算: $$ S = (1 + p_1 + p_1^2 + \cdots + p_1^{a_1}) \times (1 + p_2 + p_2^2 + \cdots + p_2^{a_2}) \times \cdots \times (1 + p_k + p_k^2 + \cdots + p_k^{a_k}) $$ 该公式基于乘法原理,将每个质因数的幂次展开后相乘,得到所有可能的约数,并将它们[^1]。 ### 等比数列的实现 对于每一个质因数 $ p_i $ 的幂次部分,其对应的是一个等比数列的: $$ 1 + p_i + p_i^2 + \cdots + p_i^{a_i} = \frac{p_i^{a_i + 1} - 1}{p_i - 1} $$ 然而,在运算环境下(例如 $ 9901 $),当 $ p_i - 1 $ 与数不互质时,无法直接使用除法,因此需要采用其他方法来处理。一种常用的方法是利用**分治法**来递归地计算等比数列的: - 当幂次 $ a_i $ 为偶数时,可以将数列划分为两部分: $$ 1 + p + p^2 + \cdots + p^{a_i} = (1 + p + p^2 + \cdots + p^{a_i/2}) + p^{a_i/2 + 1}(1 + p + p^2 + \cdots + p^{a_i/2}) $$ - 当幂次 $ a_i $ 为奇数时,可以提取出最后一项 $ p^{a_i} $,使得剩余部分为偶数项,从而递归处理。 ### Python 实现代码示例 以下是一个基于分治思想实现的等比数列函数,并结合质因数分解计算约数之和的完整实现: ```python def power_mod(p, power, mod): """计算 p^power % mod""" result = 1 base = p % mod while power: if power % 2 == 1: result = (result * base) % mod base = (base * base) % mod power //= 2 return result def geometric_sum(p, power, mod): """使用分治法计算等比数列 (1 + p + p^2 + ... + p^power) % mod""" if power == 0: return 1 if power % 2 == 0: # 偶数:1 + p + ... + p^{k} = (1 + p^{k/2}) * (1 + p + ... + p^{k/2-1}) return (geometric_sum(p, power // 2 - 1, mod) * (1 + power_mod(p, power // 2, mod))) % mod else: # 奇数:1 + p + ... + p^{k} = (1 + p^{k/2}) * (1 + p + ... + p^{k/2}) + p^{k} return (geometric_sum(p, power // 2, mod) * (1 + power_mod(p, power // 2 + 1, mod)) + power_mod(p, power, mod)) % mod def get_divisor_sum(n, mod): """计算 n 的所有正约数之和 % mod""" result = 1 i = 2 while i * i <= n: count = 0 while n % i == 0: count += 1 n //= i if count: result = (result * geometric_sum(i, count, mod)) % mod i += 1 if n > 1: result = (result * geometric_sum(n, 1, mod)) % mod return result # 示例:计算 20 的所有正约数之和 % 9901 print(get_divisor_sum(20, 9901)) # 输出 42 ``` ### 说明 - `power_mod` 函数用于高效计算幂的运算。 - `geometric_sum` 函数使用分治法递归计算等比数列的。 - `get_divisor_sum` 函数通过质因数分解等比数列,最终得到正整数的所有正约数之和。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值