题干:
给定a、b,求
的所有因子和,结果模9901.
0 <= A,B <= 50000000
思路:
根据唯一分解定理:a=
*
*
…
(Pi为素数)
所以a的因子和可以写成:ans=(1+
+
…
) * (1+
+
…
) …*(1+
+
…
)
所以 的因子和可以写成:ans=(1+ + … ) * (1+ + … ) …*(1+ + … )
观察(1+
+
…
) 可得这是一个等比数列的和,可以写成
(
-1)/(P1-1)%9901.
因为除法不能取余,所以我们对(P1-1)取乘法逆元,变成:
(
-1)-1%(9901*(P1-1))/(P1-1)
因为牵扯到减法所以变成:
(
-1)+(9901*(P1-1))-1%(9901*(P1-1))/(P1-1)
然后对 做快速幂,为了防止乘的中途爆数据,使用快速乘(即将一个乘数按二进制乘然后相加)。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
const ll mod=9901;
const int mx=50005;
int f[mx],p[mx],num;
void f1()
{
for(int i=2;i<mx;i++){
if(!f[i]) p[num++]=i;
for(int j=0;j<num&&i*p[j]<mx;j++){
f[i*p[j]]=1;
if(!(i%p[j])) break;
}
}
}
ll mul(ll a,ll b,ll c)
{
a%=c;
b%=c;
ll ans=0;
while(b)
{
if(b&1)
ans=(ans+a)%c;
a=(a+a)%c;
b>>=1;
}
return ans%c;
}
ll qc(ll a,ll b,ll c)
{
ll ans=1;
while(b)
{
if(b&1)
ans=mul(ans,a,c);
a=mul(a,a,c);
b>>=1;
}
return ans%c;
}
int main()
{
ll a,b;
f1();
scanf("%lld %lld",&a,&b);
ll ans=1;
for(int i=0;p[i]*p[i]<=a;i++){
int sum=0;
if(a%p[i]==0)
{
while(a%p[i]==0)
{
sum++;
a/=p[i];
}
ll m=(p[i]-1)*mod;
ans*=(qc(p[i],sum*b+1,m)+m-1)/(p[i]-1);
ans%=mod;
}
//printf("%lld\n",ans);
}
if(a>1)
{
ll m=(a-1)*mod;
ans*=(qc(a,b+1,m)+m-1)/(a-1);
ans%=mod;
}
printf("%lld\n",ans);
return 0;
}