欢迎大家访问我的老师的OJ———caioj.cn
题面描述
思路
一句话题意:求 A B A^B AB的所有约数之和 mod 9901 ( 1 ≤ A , B ≤ 5 ∗ 1 0 7 ) \operatorname{mod}9901(1\le A,B\le 5*10^7) mod9901(1≤A,B≤5∗107)
提要:
等比数列求和公式: S n = a 1 ∗ 1 − q n 1 − q S_n=a_1*\frac{1-q^n}{1-q} Sn=a1∗1−q1−qn,其中 q q q为公比(与公差类似)
乘法逆元:
若整数
b
,
m
b,m
b,m互质,且
b
∣
a
b\mid a
b∣a,则存在一个整数x,使得
a
/
b
≡
a
∗
x
(
mod
m
)
a/b \equiv a*x(\operatorname{mod} m)
a/b≡a∗x(modm),
则称
x
x
x为
b
b
b的模
m
m
m乘法逆元,记为
b
−
1
(
mod
m
)
b^{-1}(\operatorname{mod} m)
b−1(modm)。
因为 a / b ≡ a ∗ b − 1 ≡ a / b ∗ b ∗ b − 1 ( mod m ) a/b\equiv a*b^{-1}\equiv a/b*b*b^{-1}(\operatorname{mod} m) a/b≡a∗b−1≡a/b∗b∗b−1(modm),所以 b ∗ b − 1 ≡ 1 ( mod m ) b*b^{-1}\equiv 1(\operatorname{mod} m) b∗b−1≡1(modm)
如果 m m m是质数的话,并且 b < m b<m b<m,根据费马小定理,可知, b m − 1 ≡ 1 ( mod m ) , 即 b ∗ b m − 2 ≡ 1 ( mod m ) b^{m-1}\equiv 1(\operatorname{mod} m),即b*b^{m-2}\equiv 1(\operatorname{mod} m) bm−1≡1(modm),即b∗bm−2≡1(modm)。
因此,当模数 m m m为质数时, b m − 2 b^{m-2} bm−2即为 b b b的乘法逆元。
由于我们这里仅涉及到 m m m为 9901 9901 9901,即为质数的情况,所以不做拓展。
由于A分解质因数,可表示为: p 1 c 1 ∗ p 2 c 2 ∗ . . . . . . ∗ p m c m p_1^{c_1}*p_2^{c_2}*......*p_m^{c_m} p1c1∗p2c2∗......∗pmcm,根据算术基本定理的“约数和”推论,
A B A^B AB的所有约数之和为: ( 1 + p 1 + p 1 2 + . . . . . . p 1 B ∗ c 1 ) ∗ . . . . . . ∗ ( 1 + p m + p m 2 + . . . . . . + p m B ∗ c m ) = ∏ i = 1 m ( ∑ j = 0 B ∗ c i ( p i ) j ) (1+p_1+p_1^2+......p_1^{B*c_1})*......*(1+p_m+p_m^2+......+p_m^{B*c_m})=\large\prod\limits_{i=1}^m(\sum\limits_{j=0}^{B*c_i}(p_i)^j) (1+p1+p12+......p1B∗c1)∗......∗(1+pm+pm2+......+pmB∗cm)=i=1∏m(j=0∑B∗ci(pi)j),
仔细观察可以发现, ∑ j = 0 B ∗ c i ( p i ) j \sum\limits_{j=0}^{B*c_i}(p_i)^j j=0∑B∗ci(pi)j其实就是一个等比数列求和,
即
(
p
i
B
∗
c
i
+
1
−
1
)
/
(
p
i
−
1
)
(p_i^{B*c_i+1}-1)/(p_i-1)
(piB∗ci+1−1)/(pi−1),这是我们只要对分子
p
i
B
∗
c
i
+
1
−
1
p_i^{B*c_i+1}-1
piB∗ci+1−1快速幂求出,
分母通过快速幂,求出乘法逆元得出即可。
特别地,对于 p i − 1 p_i-1 pi−1是 9901 9901 9901的倍数,此时乘法逆元并不存在,但是 p 1 mod 9901 = 1 p_1 \operatorname{mod} 9901 =1 p1mod9901=1,所以 1 + p 1 + p 1 2 + . . . . . . + p 1 b ∗ c 1 ≡ 1 + 1 + 1 2 + . . . . . . + 1 B ∗ c 1 ≡ B ∗ c 1 + 1 ( mod 9901 ) . 1+p_1+p_1^2+......+p_1^{b*c_1}\equiv 1+1+1^2+......+1^{B*c_1}\equiv B*c_1+1(\operatorname{mod} 9901). 1+p1+p12+......+p1b∗c1≡1+1+12+......+1B∗c1≡B∗c1+1(mod9901).
AC code
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cstdlib>
#define ll long long
#define gc getchar()
using namespace std;
const int N=15;
const int mod=9901;
ll p[N];int c[N];
inline void qr(ll &x)
{
x=0;int f=1;char c=gc;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
x*=f;
}
inline void mul(ll &a,ll b)
{
ll c=a*b/mod;
a=a*b-c*mod;
}
inline ll pow_mod(ll a,ll b)
{
ll ans=1;a%=mod;
while(b)
{
if(b&1)mul(ans,a);
b>>=1;mul(a,a);
}
return ans;
}
inline void div(ll x)
{
p[0]=0;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
p[++p[0]]=i;
c[p[0]]=0;
while(x%i==0)x/=i,++c[p[0]];
}
}
if(x>1)p[++p[0]]=x,c[p[0]]=1;
}
int main()
{
ll a,b;qr(a),qr(b);
div(a);ll ans=1;
for(int i=1;i<=p[0];i++)
{
if((p[i]-1)%mod==0)
{
ans=(b*c[i]+1)*ans%mod;
continue;
}
ll x=pow_mod(p[i],b*c[i]+1);
x=(x-1+mod)%mod;
ll y=p[i]-1;
y=pow_mod(y,mod-2);
ans=ans*x*y%mod;
}
printf("%lld\n",ans);
return 0;
}