10211. 「一本通 6.4 例 3」Sumdiv[数论之约数与快速幂]
【题目描述】
原题来自:Romania OI 2002
求 ABAB 的所有约数之和 mod9901mod9901。
【输入】
输入两个整数 A,BA,B。
【输出】
输出答案 mod9901mod9901。
【输入样例】
2 3
【输出样例】
15
【提示】
样例说明
23=823=8,88 的所有约数为 1,2,4,81,2,4,8,1+2+4+8=151+2+4+8=15,15mod9901=1515mod9901=15,因此输出 1515。
数据范围与提示:
对于全部数据,0≤A,B≤5×1070≤A,B≤5×107。
分析:题目谈到约数和,我们就想到约数和的公式:
设A惟一分解后等于
p
1
a
1
p_1^{a1}
p1a1×
p
2
a
2
p_2^{a2}
p2a2 …
p
n
a
n
p_n^{an}
pnan,则A的约数和为
Π
i
=
1
n
(
Σ
j
=
0
a
i
(
p
i
)
j
)
\Pi_{i=1}^n(\Sigma_{j=0}^{ai}(p_i) ^j)
Πi=1n(Σj=0ai(pi)j)
注意后者是一个等比数列,则想到等比数列求和公式,将其化简得到
Π
i
=
1
n
(
p
i
a
i
+
1
−
1
p
i
−
1
)
\Pi_{i=1}^n(\frac{p_i^{ai+1}-1}{p_i-1})
Πi=1n(pi−1piai+1−1)
带入题目要求的B和模数9901(质数)得到
a
n
s
=
Π
i
=
1
n
(
p
i
a
i
×
B
+
1
−
1
p
i
−
1
m
o
d
9901
)
ans=\Pi_{i=1}^n(\frac{p_i^{ai ×B+1}-1}{p_i-1} mod 9901)
ans=Πi=1n(pi−1piai×B+1−1mod9901)
于是算出
p
i
−
1
p_i-1
pi−1的乘法逆元即可
代码如下
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,B;
ll p[100010];
ll b[100010];
ll cnt;
ll KSM(ll j,ll k,ll l)
{
ll ans=1;
while(k)
{
if(k&1) ans=ans*j%l;
j=j*j%l;
k>>=1;
}
return ans;
}
int main()
{
scanf("%lld%lld",&a,&B);//输入
for(ll i=2;i*i<=a;i++)
{
if(a%i==0)
{
p[++cnt]=i;
while(a%i==0)
{
b[cnt]++;
a/=i;
}
}
}
if(a>1)
{
p[++cnt]=a;
b[cnt]=1;
}//质因数分解,p为底数,b为指数
ll ans=1;
for(ll i=1;i<=cnt;i++)
{
ans*=((KSM(p[i],b[i]*B+1,9901)+9900)%9901)*(KSM(p[i]-1,9901-2,9901))%9901;//算出答案
//根据费马小定理,可知pi-1的乘法逆元是(pi-1)^(9901-2),用快速幂算出
}
printf("%lld",ans%9901);//别忘了还要取模
return 0;
}
如有错误,可留言,谢谢