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;
}
posted @ 2019-08-26 10:30  惜时如金  阅读(199)  评论(0编辑  收藏  举报