题目描述
假设现在有两个自然数 A A A 和 B B B, S S S 是 A B A^B AB 的所有约数之和。
请你求出 S m o d 9901 S\ mod\ 9901 S mod 9901 的值是多少。
输入格式
在一行中输入用空格隔开的两个整数 A A A 和 B B B。
输出格式
输出一个整数,代表 S m o d 9901 S\ mod\ 9901 S mod 9901 的值。
数据范围
0 ≤ A , B ≤ 5 × 1 0 7 0≤A,B≤5×10^7 0≤A,B≤5×107
输入样例
2 3
输出样例
15
注意: A A A 和 B B B 不会同时为 0 0 0。
题目分析
设 A A A 可以分解质因数为: A = a 1 i 1 ∗ a 2 i 2 ∗ … ∗ a n i n A={a_1}^{i_1}*{a_2}^{i_2}*…*{a_n}^{i_n} A=a1i1∗a2i2∗…∗anin,那么 C = A B = a 1 B ∗ i 1 ∗ a 2 B ∗ i 2 ∗ … ∗ a n B ∗ i n C=A^B={a_1}^{B*i_1}*{a_2}^{B*i_2}*…*{a_n}^{B*i_n} C=AB=a1B∗i1∗a2B∗i2∗…∗anB∗in,根据乘法原理知 C C C 的约数之和 S = ( 1 + a 1 + a 1 2 + … + a 1 B ∗ i 1 ) ∗ ( 1 + a 2 + a 2 2 + … + a 2 B ∗ i 2 ) ∗ … ∗ ( 1 + a n + a n 2 + … + a n B ∗ i n ) S=(1+a_1+{a_1}^2+…+{a_1}^{B*i_1})*(1+a_2+{a_2}^2+…+{a_2}^{B*i_2})*…*(1+a_n+{a_n}^2+…+{a_n}^{B*i_n}) S=(1+a1+a12+…+a1B∗i1)∗(1+a2+a22+…+a2B∗i2)∗…∗(1+an+an2+…+anB∗in)。上面的每个括号内都是等比数列,如果直接等比数列求和要用除法,但取模运算只对加、减、乘有分配律,不能直接对除法中的分子、分母取模后再做除法。因此,我们需要换一种方法对等比数列求和。
设 s u m ( a , i ) = 1 + a + a 2 + … + a i sum(a,i)=1+a+a^2+…+a^i sum(a,i)=1+a+a2+…+ai发现如下性质:
若 i i i 为奇数,那么
s u m ( a , i ) sum(a,i) sum(a,i)
= ( 1 + a + … + a i − 1 2 ) + ( a i + 1 2 + … + a i ) =(1+a+…+a^\frac{i-1}2)+(a^\frac{i+1}2+…+a^i) =(1+a+…+a2i−1)+(a2i+1+…+ai)
= ( 1 + a i + 1 2 ) ∗ s u m ( p , i − 1 2 ) =(1+a^\frac{i+1}2)*sum(p,\frac{i-1}2) =(1+a2i+1)∗sum(p,2i−1)
类似地,若 i i i 为偶数,那么 s u m ( a , i ) = ( 1 + a i 2 ) ∗ s u m ( p , c 2 − 1 ) + a i sum(a,i)=(1+a^\frac i2)*sum(p,\frac c2-1)+a^i sum(a,i)=(1+a2i)∗sum(p,2c−1)+ai
运用分治思想与快速幂,可以在 O ( l o g c ) O(logc) O(logc) 的复杂度内求出等比数列的和。
代码:
#include <iostream>
using namespace std;
const int MOD = 9901;
int x, y;
int quick_pow(int a, int b){
a %= MOD;
int res = 1;
while (b){
if (b & 1) res = res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
int sum(int a, int b){
if (!b) return 1;
if (b & 1) return (1 + quick_pow(a, (b + 1) / 2)) * sum(a, (b - 1) / 2) % MOD;
else return ((1 + quick_pow(a, b / 2)) * sum(a, b / 2 - 1) + quick_pow(a, b)) % MOD;
}
int result(int a, int b){
int res = 1;
for (int i = 2; i <= a; i ++){
int num = 0;
while (a % i == 0){
num ++;
a /= i;
}
if (num) res = res * sum(i, b * num) % MOD;
}
return res;
}
int main(){
cin >> x >> y;
if (!x) cout << 0;
else cout << result(x, y);
return 0;
}