题目描述
求 ABAB 的所有约数之和 mod9901mod9901。1≤A,B≤5×1071≤A,B≤5×107。
算法分析
根据之前博客的题解,ABAB 的约数之和为 (p00+p10+...+pc0B0)×(p01+p11+...+pc1B1)×...×(p0n+p1n+...+pcnBn)(p00+p01+...+p0c0B)×(p10+p11+...+p1c1B)×...×(pn0+pn1+...+pncnB)。
利用等比数列求和公式计算即可,公式涉及除法时可以使用费马小定理计算出分母的逆元。
注意,在模意义下,减去一个数后一定要再加上模数,不然结果可能出现负数。
代码实现
#include <cstdio>
#include <vector>
typedef long long int ll;
const ll mod=9901;
std::vector<ll> prime;
std::vector<ll> times;
inline void divide(ll n) {
for(ll i=2;i*i<=n;++i) {
if(n%i==0) {
prime.push_back(i);ll cnt=0;
while(n%i==0) {n/=i;++cnt;}
times.push_back(cnt);
}
}
if(n>1) {prime.push_back(n);times.push_back(1);}
}
inline ll qpow(ll n,ll k) {
ll ans=1;
while(k) {
if(k&1) ans=ans*n%mod;
n=n*n%mod;k>>=1;
}
return ans;
}
int main() {
ll a,b;scanf("%lld%lld",&a,&b);
divide(a);
ll ans=1;
for(int i=0,end=prime.size();i<end;++i) {
times[i]*=b;
if((prime[i]-1)%mod==0) ans=ans*(times[i]+1)%mod;
else ans=ans*((qpow(prime[i],times[i]+1)-1+mod)*qpow(prime[i]-1,mod-2)%mod)%mod;
}
printf("%lld\n",ans);
return 0;
}