题目描述:
假设现在有两个自然数A和B,S是A^B的所有约数之和。
请你求出S mod 9901的值是多少。
输入格式
在一行中输入用空格隔开的两个整数A和B。
输出格式
输出一个整数,代表S mod 9901的值。
数据范围
0≤A,B≤5×1070≤A,B≤5×107
输入样例:
2 3
输出样例:
15
注意: A和B不会同时为0。
分析:
公式推导:
第一步,质因数分解:由算术基本定理得任意一个数A = p1^k1 * p2^k2 * … * pn^kn。(其中p1-pn为A所有的质因数),则A^B = p1^k1B * p2^k2B * … * pn^knB。
第二步(补充),因子个数,设x为A的一个约数,则x必定可由若干个p1-pn相乘得到,对于任一个质因子pi,可为其他因子贡献的数量为从0到ki,共1+ki个。由乘法原理得,数A所有的因子个数为C = (k1+1) * (k2+1) * … * (kn + 1).
第三步,因子和,设Sn = (p1^0 + p1 ^1 + … + p1^k1)* (p2^0 + p2 ^1 + … + p2^k2)* … * (pn^0 + pn ^1 + … + pn^kn),展开可得到C项,每一项都是A的因子。
第四步,公式推导,设sum(p,k) = p^0 + p ^1 + … + p^k. 一共k+1项,我们对k分类讨论,k为奇数时,k+1为偶数,例如k = 7,sum(p,7) = (p^0 + p^1 + p^2 + p^3 ) + (p^4 + p^5 + p^6 + p^7)
我们对其分成数量相等的两组式子,又p^4 + p^5 + p^6 + p^7 = p^4 * (p^0 + p^1 + p^2 + p^3 ),所以sum(p,7) = (p^0 + p^1 + p^2 + p^3 ) * (1 + p^4).更一般的,sum(p,k) = (p^0 + p^1 + … + p^k/2 ) * (1 + p^(k/2+1) ) = sum(p,k/2) * (1 + p^(k/2+1) ) ,其中k为奇数.
k为偶数时,k+1为奇数,sum(p,k) = p^0 + p ^1 + … + p^k = 1 + p * (p^0 + p ^1 + … + p^(k-1) ) = 1 + p * sum(p,k-1).
当然,最后需要注意的是,我们求A^B的约数和时,调用的sum(p,k),k应该是第一步推导的kB。并且k为奇数时,我们求幂可以使用快速幂算法。
#include <iostream>
using namespace std;
const int mod = 9901;
int binarypow(int a,int k){
a %= mod;
int res = 1;
while(k){
if(k & 1) res = res * a % mod;
a = a * a % mod;
k >>= 1;
}
return res;
}
int sum(int p,int k){
if(k == 0) return 1;
if(k % 2 == 0) return (p % mod * sum(p,k - 1) % mod + 1) % mod;
return sum(p,k/2) % mod * (1+binarypow(p,k/2+1)) % mod;
}
int main(){
int A,B;
cin>>A>>B;
int res = 1;
for(int i = 2;i <= A;i++){
int s = 0;
while(A % i == 0){
s++;
A /= i;
}
if(s) res = res * sum(i,s * B) % mod;
}
if(!A) res = 0;
cout<<res<<endl;
return 0;
}