题目链接: POJ1845
题目大意: 给出
A
,
B
A,B
A,B,求
A
B
A^{B}
AB中所有因数的和。
题目分析: 对于一个数
A
A
A我们可以把它写成
A
=
p
1
k
1
∗
p
2
k
2
∗
.
.
.
∗
p
m
k
m
A=p1^{k1}*p2^{k2}*...*pm^{km}
A=p1k1∗p2k2∗...∗pmkm
那么对于
A
B
A^{B}
AB就可以写成
A
B
=
p
1
B
k
1
∗
p
2
B
k
2
∗
.
.
.
∗
p
m
B
k
m
A^{B}=p1^{Bk1}*p2^{Bk2}*...*pm^{Bkm}
AB=p1Bk1∗p2Bk2∗...∗pmBkm
而对于一个数,它的因数和可以写成
∑
n
∣
d
=
(
1
+
p
1
+
p
1
2
+
.
.
.
+
p
1
k
1
)
(
1
+
p
2
+
p
2
2
+
.
.
.
+
p
2
k
2
)
.
.
.
(
1
+
p
m
+
p
m
2
+
.
.
.
+
p
m
k
m
)
\sum_{n|d}=(1+p1+p1^2+...+p1^{k1}) (1+p2+p2^2+...+p2^{k2})...(1+pm+pm^2+...+pm^{km})
∑n∣d=(1+p1+p12+...+p1k1)(1+p2+p22+...+p2k2)...(1+pm+pm2+...+pmkm)
对于一个括号内的多项式,可以看做是等比数列的前缀和的形式,但由于题目要对答案取模,而模运算中的除法不满足分配律,因此这里递归求解
分类讨论,当
k
k
k为奇数时
f
(
p
,
k
)
=
(
1
+
p
+
.
.
.
+
p
k
−
1
2
)
+
(
p
k
+
1
2
+
.
.
.
+
p
k
)
f(p,k)=(1+p+...+p^{\frac{k-1}{2}})+(p^{\frac{k+1}{2}}+...+p^{k})
f(p,k)=(1+p+...+p2k−1)+(p2k+1+...+pk)
f
(
p
,
k
)
=
(
1
+
p
k
+
1
2
)
(
1
+
p
+
.
.
.
+
p
k
−
1
2
)
f(p,k)=(1+p^{\frac{k+1}{2}})(1+p+...+p^{\frac{k-1}{2}})
f(p,k)=(1+p2k+1)(1+p+...+p2k−1)
f
(
p
,
k
)
=
(
1
+
p
k
+
1
2
)
f
(
p
,
k
−
1
2
)
f(p,k)=(1+p^{\frac{k+1}{2}})f(p,\frac{k-1}{2})
f(p,k)=(1+p2k+1)f(p,2k−1)同理当
k
k
k为偶数时
f
(
p
,
k
)
=
(
1
+
p
+
.
.
.
+
p
k
2
−
1
)
+
(
p
k
2
+
.
.
.
+
p
k
−
1
)
+
p
k
f(p,k)=(1+p+...+p^{\frac{k}{2}-1})+(p^{\frac{k}{2}}+...+p^{k-1})+p^{k}
f(p,k)=(1+p+...+p2k−1)+(p2k+...+pk−1)+pk
f
(
p
,
k
)
=
(
1
+
p
k
2
−
1
)
(
1
+
p
+
.
.
.
+
p
k
2
)
+
p
k
f(p,k)=(1+p^{\frac{k}{2}-1})(1+p+...+p^{\frac{k}{2}})+p^k
f(p,k)=(1+p2k−1)(1+p+...+p2k)+pk
f
(
p
,
k
)
=
(
1
,
p
k
2
−
1
)
f
(
p
,
k
2
)
+
p
k
f(p,k)=(1,p^{\frac{k}{2}-1})f(p,\frac{k}{2})+p^k
f(p,k)=(1,p2k−1)f(p,2k)+pk
这样复杂度大约是
O
(
m
(
约
数
个
数
)
l
o
g
(
m
)
)
O(m(约数个数)log(m))
O(m(约数个数)log(m))
下面是完整代码。
题目代码:
#include<stdio.h>
#define LL long long
#define mod 9901
int prime[1100000],not_prime[1100000],cnt,Cnt;
LL ans=1;
struct Divisor{
LL p,k;
}divisor[1100000];
LL ksm(LL a,LL b){
if(b==0)return 1;
LL v=ksm(a,b/2);
if(b%2)return v*v%mod*a%mod;
else return v*v%mod;
}
LL Work(LL p,LL k){
if(k==0)return 1;
if(k%2)return Work(p,k/2)*(1+ksm(p,k/2+1))%mod;
if(!(k%2))return (Work(p,k/2-1)*(1+ksm(p,k/2))%mod+ksm(p,k))%mod;
}
bool Check(LL a){
for(int i=2;i*i<=a;i++)
if(a%i==0)return false;
return true;
}
int main()
{
LL n,m;
scanf("%lld %lld",&n,&m);
if(n==0&&m==0){
printf("1\n");
return 0;
}
for(int i=2;i<=1000000;i++){
if(!not_prime[i]){
int cc=i;
while(cc+i<=1000000){
cc+=i;
not_prime[cc]=1;
}
prime[++cnt]=i;
}
}
for(int i=1;i<=cnt;i++){
if(n%prime[i])continue;
int c=0;
while(!(n%prime[i]))n/=prime[i],c++;
divisor[++Cnt].p=prime[i];
divisor[Cnt].k=c;
}
if(Check(n)&&n>1000000){
divisor[++Cnt].p=n;
divisor[Cnt].k=1;
}
for(int i=1;i<=Cnt;i++)
ans=(ans*Work(divisor[i].p,divisor[i].k*m)%mod)%mod;
printf("%lld\n",ans);
return 0;
}