假设现在有两个自然数A和B,S是AB的所有约数之和。
请你求出S mod 9901的值是多少。
输入格式
在一行中输入用空格隔开的两个整数A和B。
输出格式
输出一个整数,代表S mod 9901的值。
数据范围
0≤A,B≤5×107
输入样例:
2 3
输出样例:
15
注意: A和B不会同时为0。
思路:
把A分解质因数,表示为p1c1 * p2c2 * …pncn。那么 A 表示为p1 Bc1^p2 B*c2…pn B*cn
AB的所有约束之和就是:(1+p1+p12+…+p1B*c1)(1+p2+p2 2 +…+p2 B*c2)…(1+pn+pn ^ 2^ +…+ pmB*cn)
上式括号内都是等比数列,如果用等比数列求和公式需要做除法。而除法取模很麻烦,需要用中国剩余定理,所以采用分治法进行等比数列求和
sum(p,c)=1+p+p^ 2 +…+ p^c
=1+p+…+p ^((c-1)/2)+p ^(c+1/2)+…+p ^c
若c为偶数:sum(p,c)=(1+p ^(c/2))*sum(p,c/2-1)+ p ^c
若c为奇数:sum(p,c)=(1+p^(c+1)/2)*sum(p,(c-1)/2);
配合快速幂求出结果
#include<iostream>
#include <vector>
#include <algorithm>
#include<cstring>
using namespace std;
const int mod = 9901;
int power(int a,int b){
a%=mod;
int ans=1;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans%mod;
}
int sum(int p,int k){
if(k==0) return 1;
if(k%2==0) return (p%mod*sum(p,k-1)+1)%mod;//提出一个p,使k变为奇数
return (1+power(p,k/2+1))*sum(p,k/2)%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;
}