POJ1845(约数之和)
自闭的人的题解
POJ1845 约数之和
题目描述:
给你两个整数A、B,让你求出a^b中所有的约数的和膜上9901的值。
输入 :
两个正整数A,B
输出 :
一个正整数表示答案
样例:
IN :2 3
OUT : 15
这道题,我一开始其实是只有暴力的思路的。
但是,又重新去思考一下,因为求的是所有约数的和,所以我们就可以将A分解质因数
\[A=p_{1}^{c_{1}} * p_{2}^{c_{2}} * p_{3}^{c_{3}} * \ldots * p_{n}^{c n_{+1}}
\]
又因为要^B,所以我们最后得到的式子就是这个:
\[\mathrm{A}=p_{1}^{B * c_{1}} * p_{2}^{B * c_{2}} * p_{3}^{B * c_{3}} * \ldots * p_{n}^{B * c_{n}}
\]
所以A^B的约数为就是:
\[\begin{array}{c}{\left\{p_{1}^{k_{1}} * p_{2}^{k_{2}} * \ldots * p_{n}^{k_{n}}\right\}} \\ {0 \leq k_{i} \leq B * c_{i}(1 \leq i \leq n)}\end{array}
\]
再将中间的约数拆开来,得到:
\[\left(1+p_{1}+p_{1}^{2}+p_{1}^{3}+p_{1}^{4} \ldots+p_{1}^{B \cdot c_{1}}\right) *\left(1+p_{2}+p_{2}^{2}+p_{2}^{3}+p_{2}^{4} \ldots+p_{2}^{B \cdot c_{2}}\right) \ldots *\left(1+p_{n}+p_{n}^{2}+p_{n}^{3}+p_{n}^{4} \ldots+p_{n}^{B \cdot c_{n}}\right)
\]
所以我们的问题就转化到了对于这个式子进行取模求和,但是,我们如何进行求和呢?
因为其中全部都是等比数列,所以如果我们就可以考虑使用等比数列求和公式进行求解,但是,我们这中间有除法,所以我们的取模操作就会出问题。所以这个思路的正确性是无法保证的。
我们可以再换一种思路,可以将问题进行
分治
我们设出一个函数sum(p,c)表示约数对答案造成的影响。
\[\operatorname{sum}(p, c)=1+p+p^{2}+p^{3}+p^{4} \ldots+p^{c}
\]
我们考虑对于c为奇数时,
\[\begin{aligned} \operatorname{sum}(p, c) &=1+p+p^{2}+p^{3}+p^{4} \ldots+p^{c} \\ &=\left(1+p+\cdots+p^{\frac{c-1}{2}}\right)+\left(p^{\frac{c+1}{2}}+\cdots+p^{c}\right) \\ &=\left(1+p+\cdots+p^{\frac{c-1}{2}}\right)+p^{\frac{c+1}{2}}\left(1+p+\cdots+p^{\frac{c-1}{2}}\right) \\ &=\left(1+p+\cdots+p^{\frac{c-1}{2}}\right) *\left(1+p^{\frac{c+1}{2}}\right) \\ &=\left(1+p^{\frac{c+1}{2}}\right) * \operatorname{sum}\left(p, \frac{c-1}{2}\right) \end{aligned}
\]
当c为偶数时,同理为了满足我们刚刚推出来的式子,我们把最后一个p单独拿出来,这样我们就可以得到跟奇数一样的情况。
所以偶数的公式为:
\[\operatorname{sum}(p, c)=\left(1+p^{\frac{c}{2}}\right) * \operatorname{sum}\left(p, \frac{c}{2}-1\right)+p^{c}
\]
这样,我们两个公式都已经推出来了,我们就可以进行操作(具体细节在代码中显示)。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
template <typename type>
void scan(type &x){
type f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
#define mod 9901
#define int ll
#define ll long long
ll ksm(ll a,ll b){
ll ans=1;
while(b){
if(b&1){
ans=ans*a%mod;
}
a=(a*a)%mod;
b>>=1;
}
return ans%mod;
}\\快速幂
ll sum(ll p,ll c){
if(c==0){
return 1;
}
if(c&1){
return (1+ksm(p,(c+1)>>1)%mod)*sum(p,(c-1)>>1)%mod;//如果为奇数
}else{
return (1+ksm(p,c>>1)%mod)*sum(p,(c>>1)-1)%mod+ksm(p,c)%mod;//如果为偶数
}
}//进行操作
ll a,ans,b;
signed main(){
scan(a);
scan(b);
ans=1;
for(int i=2;i<=a;i++){
int num=0;
while(a%i==0){
num++;
a/=i;
}
if(num)
ans=ans*sum(i,b*num)%mod;
}
if(a==0){
puts("0");
}else{
printf("%lld\n",ans%mod);
}
return 0;
}