【乘法逆元】 约数之和
传送门
题意
给定 \(A,B\),求 \(A^{B}\) 的所有约数之和,答案 \(mod 9901\)
数据范围
\(0\leq A,B\leq 5\times 10^{7}\)
题解
A分解质因数后为
\[p_1^{c_{1}}\times p_2^{c_{2}}\times \cdots p_n^{c_{n}}
\]
\[A^{B}=p_1^{c_{1}\times B}\times p_2^{c_2\times B}\times \cdots p_n^{c_n\times B}
\]
那么AB的约数之和就是
\[(p_1^0+p_1^1+\cdots p_1^{c_1\times B})\times (p_2^0+p_2^1+\cdots p_2^{c_2\times B})\times \cdots \times (p_n^0+p_n^1+\cdots p_n^{c_n*\times })
\]
分解质因数后对每一项等比数列求和
每一项的求和公式为:
\[\frac {1 - p_i^{c_i\times B+1}}{1-p_i}
\]
\[\frac{p_i^{c_i\times B+1}-1}{p_i-1}
\]
分母快速幂求得\(mod~~9901\)的值
因为9901为质数,只要\(p_{i-1}\)不是他的倍数,就互质,根据费马小定理可以求出逆元,
如果是倍数,那么\(p_i ~~mod ~~9901\)为1
所以等比数列和就是\(B\times c_i+1\)
Code
#include<bits/stdc++.h>
#define pll pair<long long,long long>
#define ll long long
using namespace std;
const int mod=9901;
pll factor[2000];
int cntf;
ll qmi(ll a,ll k){
ll res=1;
while(k){
if(k&1) res=res*a%mod;
a=a*a%mod;
k>>=1;
}
return res % mod;
}
void get(ll a){
for(ll i=2;i<=a/i;i++){
if(a%i==0){
int num=0;
while(a%i==0){
num++;
a/=i;
}
factor[cntf++]={i,num};
}
}
if(a>1) factor[cntf++]={a,1};
}
int main(){
ll a,b;
cin>>a>>b;
if(a==0)//特判
{
puts("0");
return 0;
}
get(a);
ll ans=1;
for(int i=0;i<cntf;i++){
int p=factor[i].first;
int n=factor[i].second;
if((p-1)%mod ==0){
ans=(ans%mod * (b%mod*n%mod+1)%mod)%mod;
}
else{
ll x=((qmi(p,b*n+1)-1)%mod+mod)%mod;// qmi求得的结果-1后可能为负数
ll y=qmi(p-1,mod-2);
ans=((ans*x)%mod*y)%mod;
}
}
cout<<ans<<endl;
return 0;
}