题目链接
一、题目分析
题目要求
A
B
A^B
AB的所有因数之和,数据范围很大,用暴力不太合适。
本题应用到一些数学知识
-
算数基本定理:任何大于1的正整数都能唯一分解为有限个质数的乘积,可写作: N = p 1 c 1 p 2 c 2 p 3 c 3 … p m c m N = p_1^{c_1}p_2^{c_2}p_3^{c_3}{\ldots}p_m^{c_m} N=p1c1p2c2p3c3…pmcm其中 c i c_i ci都是正整数, p i p_i pi都是质数,且满足 p 1 < p 2 < … < p m p_1<p_2< {\ldots} <p_m p1<p2<…<pm
那么可以将输入的A进行质因数分解,
A = p 1 c 1 p 2 c 2 p 3 c 3 … p m c m A = p_1^{c_1}p_2^{c_2}p_3^{c_3}{\ldots}p_m^{c_m} A=p1c1p2c2p3c3…pmcm
同样有
A B = p 1 c 1 ∗ B p 2 c 2 ∗ B p 3 c 3 ∗ B … p m c m ∗ B A^B= p_1^{c_1*B}p_2^{c_2*B}p_3^{c_3*B}{\ldots}p_m^{c_m*B} AB=p1c1∗Bp2c2∗Bp3c3∗B…pmcm∗B
A B A^B AB的因数集合可以表示为 { p 1 c 1 ∗ p 2 c 2 ∗ p 3 c 3 ∗ … ∗ p m c m } \{p_1^{c_1}*p_2^{c_2}*p_3^{c_3}*{\ldots}*p_m^{c_m}\} {p1c1∗p2c2∗p3c3∗…∗pmcm}其中 0 ⩽ k i ⩽ B ∗ c i ( 1 ⩽ i ⩽ n ) 0{\leqslant}k_i{\leqslant}B*c_i(1{\leqslant}i{\leqslant}n) 0⩽ki⩽B∗ci(1⩽i⩽n)
利用乘法分配律(类似组合的过程,从每个括号里选一个数,然后乘起来),可以将因数相加转化为多组乘法 -
( 1 + p 1 1 + p 1 2 + … + p 1 c 1 ∗ B ) ∗ ( 1 + p 2 1 + p 2 2 + … + p 1 c 1 ∗ B ) ∗ … ∗ ( 1 + p n 1 + p n 2 + … + p n c n ∗ B ) (1+p_1^{1}+p_1^{2}+{\ldots}+p_1^{c_1*B})*(1+p_2^{1}+p_2^{2}+{\ldots}+p_1^{c_1*B})*{\ldots}*(1+p_n^{1}+p_n^{2}+{\ldots}+p_n^{c_n*B}) (1+p11+p12+…+p1c1∗B)∗(1+p21+p22+…+p1c1∗B)∗…∗(1+pn1+pn2+…+pncn∗B)
每个括号中的内容均为等比数列,等比数列求和可以采用公式法,但是,对除法运用模运算不存在分配性(可以通过逆元解决,这里先不进行讨论)。考虑采用分治法的思想解决问题。所谓分治法即将问题分解为多个子问题,对子问题求解后,再合并为原问题。等比数列求和:
s
u
m
(
p
,
c
)
=
1
+
p
1
+
p
2
+
…
+
p
c
sum(p,c) = 1+p^{1}+p^{2}+{\ldots}+p^{c}
sum(p,c)=1+p1+p2+…+pc
若c为奇数:
s
u
m
(
p
,
c
)
=
(
1
+
p
1
+
p
2
+
…
+
p
(
c
−
1
)
/
2
)
+
(
p
(
c
+
1
)
/
2
+
…
+
p
c
)
sum(p,c) = (1+p^{1}+p^{2}+{\ldots}+p^{(c - 1)/2})+(p^{(c + 1)/2} + {\ldots} + p^c)
sum(p,c)=(1+p1+p2+…+p(c−1)/2)+(p(c+1)/2+…+pc)
=
(
1
+
p
+
⋯
+
p
(
c
−
1
)
/
2
)
+
p
(
c
+
1
)
/
2
∗
(
1
+
p
+
⋯
+
p
(
c
−
1
)
/
2
)
=(1+p+\dots+p^{(c-1)/2})+p^{(c+1)/2}*(1+p+\dots+p^{(c-1)/2})
=(1+p+⋯+p(c−1)/2)+p(c+1)/2∗(1+p+⋯+p(c−1)/2)
=
(
1
+
p
(
c
+
1
)
/
2
)
∗
s
u
m
(
p
,
(
c
−
1
)
/
2
)
=(1+p^{(c+1)/2})∗sum(p,(c - 1)/2)
=(1+p(c+1)/2)∗sum(p,(c−1)/2)
若c为偶数,同理可得:
s
u
m
(
p
,
c
)
=
(
1
+
p
c
/
2
)
∗
s
u
m
(
p
,
c
/
2
−
1
)
+
p
c
sum(p,c) = (1 + p^{c / 2})*sum(p,c/2 - 1)+p^c
sum(p,c)=(1+pc/2)∗sum(p,c/2−1)+pc
二、代码
#include<bits/stdc++.h>
using namespace std;
long long m = 9901;
int pow(int a,int b)
{
int ans = 1 % m;
for(; b; b >>= 1){
if(b & 1) ans = (long long)ans * a % m;
a = (long long)a * a % m;
}
return ans;
}
int sum(int p,int c)//分治法计算等比数列和
{
if(c == 0) return 1;
if(c % 2 == 0){
return ((1 + pow(p,c >> 1)) * sum(p,(c >> 1) - 1) + pow(p,c)) % m;
}
else if(c % 2 == 1){
return (sum(p,(c-1) >> 1) * (pow(p,(c + 1) >> 1) + 1)) % m;
}
}
int main()
{
int a,b;
cin >> a >> b;
// cout << pow(a,b) << endl;
// cout << sum(a,b) << endl;
if(a == 0){
cout << 0 << endl;
return;
}
int ans = 1;
for(int i = 2;i <= a;++i){
int j = 0;
while(a % i == 0){
++j;
a/=i;
}
// cout << i << ' ' << j << endl;
ans *= sum(i,j * b);
ans = ans % m;
}
cout << ans << endl;
}