题目链接:POJ 1845
题意
求 ab a b 的所有约数之和,最终结果对9901求模
需要知识
1、快速幂:二分法求
nm
n
m
的结果
2、因数分解:遍历求出所有因数
3、约数和定理:假设n=
p1a1∗p2a2∗...pnan
p
1
a
1
∗
p
2
a
2
∗
.
.
.
p
n
a
n
, 其中
pi
p
i
都是素数,
那么n的约束之和f(n)=
(1+p11+...p1a1)∗(1+p21+...p2a2)...(1+pn1+...pnan)
(
1
+
p
1
1
+
.
.
.
p
1
a
1
)
∗
(
1
+
p
2
1
+
.
.
.
p
2
a
2
)
.
.
.
(
1
+
p
n
1
+
.
.
.
p
n
a
n
)
。
题目分析
题目是求
ab
a
b
的约数之和,那么假设a=
p1a1∗p2a2∗...pnan
p
1
a
1
∗
p
2
a
2
∗
.
.
.
p
n
a
n
,
则
ab
a
b
=
(p1a1∗p2a2∗...pnan)b
(
p
1
a
1
∗
p
2
a
2
∗
.
.
.
p
n
a
n
)
b
=
p1a1∗b∗p2a2∗b∗...pnan∗b
p
1
a
1
∗
b
∗
p
2
a
2
∗
b
∗
.
.
.
p
n
a
n
∗
b
,
从约数和定理可知,
ab
a
b
的约数之和 f(
ab
a
b
) =
(1+p11+...p1a1∗b)∗(1+p21+...p2a2∗b)...(1+pn1+...pnan∗b)
(
1
+
p
1
1
+
.
.
.
p
1
a
1
∗
b
)
∗
(
1
+
p
2
1
+
.
.
.
p
2
a
2
∗
b
)
.
.
.
(
1
+
p
n
1
+
.
.
.
p
n
a
n
∗
b
)
.
回到一般情况,这样就转化成求
1+p1+...pn
1
+
p
1
+
.
.
.
p
n
.
假设n是奇数,则一共有偶数项,此时
1+p1+...pn
1
+
p
1
+
.
.
.
p
n
=
(1+pn2+1)∗(1+p1+...pn2)
(
1
+
p
n
2
+
1
)
∗
(
1
+
p
1
+
.
.
.
p
n
2
)
.
例如n = 5时,
1+p1+p2+p3+p4+p5
1
+
p
1
+
p
2
+
p
3
+
p
4
+
p
5
=
(1+p3)(1+p+p2)
(
1
+
p
3
)
(
1
+
p
+
p
2
)
假设n是偶数,则一共有奇数项,这个时候我们将最后一项单独计算,剩下的就是偶数项,可以按照上面的方法进行计算。
此时
1+p1+...pn
1
+
p
1
+
.
.
.
p
n
=
(1+pn2)∗(1+p1+...pn2−1)+pn
(
1
+
p
n
2
)
∗
(
1
+
p
1
+
.
.
.
p
n
2
−
1
)
+
p
n
例如n = 6时,
1+p1+p2+p3+p4+p5+p6
1
+
p
1
+
p
2
+
p
3
+
p
4
+
p
5
+
p
6
=
(1+p3)(1+p+p2)+p6
(
1
+
p
3
)
(
1
+
p
+
p
2
)
+
p
6
这样根据奇偶性递归下去即可求出
1+p1+...pn
1
+
p
1
+
.
.
.
p
n
的结果。
思路总结
假设a=
p1a1∗p2a2∗...pnan
p
1
a
1
∗
p
2
a
2
∗
.
.
.
p
n
a
n
,
则
ab=(p1a1∗p2a2∗...pnan)b
a
b
=
(
p
1
a
1
∗
p
2
a
2
∗
.
.
.
p
n
a
n
)
b
=
p1a1∗b∗p2a2∗b∗...pnan∗b
p
1
a
1
∗
b
∗
p
2
a
2
∗
b
∗
.
.
.
p
n
a
n
∗
b
(1)根据约数和定理,题目所有的结果转化成
求
(1+p11+...p1a1∗b)∗(1+p21+...p2a2∗b)...(1+pn1+...pnan∗b)
(
1
+
p
1
1
+
.
.
.
p
1
a
1
∗
b
)
∗
(
1
+
p
2
1
+
.
.
.
p
2
a
2
∗
b
)
.
.
.
(
1
+
p
n
1
+
.
.
.
p
n
a
n
∗
b
)
的结果
(2)对于每项
pi
p
i
和
ai
a
i
,求出
(1+pi1+pi2+...piai∗b)
(
1
+
p
i
1
+
p
i
2
+
.
.
.
p
i
a
i
∗
b
)
,利用上面分析的奇偶性递归下去即可求出。
(3)相乘起来即为答案。
注意点
根据题目数据情况,数据类型要用long long int
如果a是素数需要特别判断
代码
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long int LL;
const LL mod = 9901;
//二分求a的b次方
LL pow_mod(LL a, LL b){
LL ret = 1;
while(b != 0){
if(b % 2 == 1){
ret = (ret * a) % mod ;
}
a = (a * a ) % mod ;
b /= 2;
}
return ret;
}
// 根据奇偶性求q的各次方之和
LL OneToN(LL q, LL n){
if(n == 0)
return 1;
if(n % 2 == 1)
return ( (1 + pow_mod(q,n/2+1) ) * OneToN(q,n/2) ) % mod;
else
return ( (1 + pow_mod(q,n/2) ) * OneToN(q, n/2 - 1) + pow_mod(q,n)) % mod;
}
int main(){
LL a ,b;
scanf("%lld %lld", &a , &b);
LL ans = 1;
LL n = a;
// cnt 是指数, i 是底数
for(LL i = 2 ; i * i <= n; i++){
int cnt = 0;
while(n % i == 0){
cnt++;
n /= i;
}
if(cnt != 0)
ans = ( ans * OneToN(i, cnt * b) ) % mod;
}
// 特判
if(n > 1)
ans = ( ans * OneToN(n, b) ) % mod;
printf("%lld\n",ans);
}