【分治】 约数之和

传送门

题意

\(A^{B}\) 的所有约数的和,答案 \(mod \: 9901\)

数据范围

\(0 \leq A,B \leq 5\times 10^{7}\)

题解

  • 唯一分解定律:一个数由质数和合数构成,合数可分解成质数和合数,最后递归下去会变成质数乘积

每一个大于1的数都可以分解成有限个质数的积,不考虑质因数的顺序,分解是唯一的,

\(A\)分解质因数后表示为:\(P_{1}^{C_{1}} \times P_{2}^{C_{2}} \times \ldots \ldots \times P_{n}^{{C_{n}}}\)

  • \(A^{B}\)约数之和就是

    • \(\left(1+P_{1}+P_{1}^{2}+\ldots P_{1}^{B ·C _{1}}\right)\times\left(1+P_{2}+P_{2}^{2}+\ldots P_{2}^{B ·C_{2}}\right)\times \ldots \left(1+P_{n}+P_{n}^{2}+\ldots . P_{n}^{B·C_{n}}\right)\)

上面每个项都是等比数列,等比数列求和需要做除法,结果需要\(mod \: 9901\),模运算只对加、减、乘有分配律

不能直接对分子分母取模再运算,分治、逆元都可以实现在模运算下对等比数列求和

定义\(sum(p,c)\)为公比为\(p\),首项为\(1\),长度为\(c\)的和

  • \(c\)为奇数时

    • \(\begin{aligned} \operatorname{sum}(p, c) &=\left(1+p+\ldots \ldots+p^{\frac{c-1}{2}}\right)+\left(p^{\frac{c+1}{2}}+\ldots \ldots+p ^{c}\right) \\ &=\left(1+p+\ldots \ldots+p^{\frac{c-1}{2}}\right)+p^{\frac{c+1}{2}} \times \left(1+p+\ldots \ldots+p^{\frac{c-1}{2}}\right) \\ &=\left(1+p^{\frac{c+1}{2}}\right)\times\operatorname{sum}(p,\frac{c-1}{2}) \end{aligned}\)
  • \(c\)为偶数时

    • \(\begin{aligned} \operatorname{sum}(p, c) &=\left(1+p+\ldots \ldots+p^{\frac{c}{2}-1}\right)+\left(p^{\frac{c}{2}}+\ldots \ldots+p^{c}\right) \\ &=\left(1+p+\ldots \ldots+p^{\frac{c}{2}-1}\right)+p^{\frac{c}{2} }\times \left(1+p+\ldots \ldots+p^{\frac{c}{2}}\right) \\ &=\left(1+p+\ldots \ldots+p^{\frac{c}{2}-1}\right)+p^{\frac{c}{2}}\left(1+p+\ldots \ldots+p^{\frac{c}{2}-1}\right)+p^{c} \\ &=\left(1+p^{\frac{c}{2}}\right)\times \operatorname{sum}(p, \frac{c}{2}-1)+p^{c} \end{aligned}\)

Code

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define ll long long
#define mod 9901
using namespace std;
ll powmod(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

ll sum(int p,int c)
{
    if(c==0) return 1;
    if(c&1) return (1+powmod(p,(c+1)>>1))%mod * sum(p,(c-1)>>1) %mod;
    else return ((1+powmod(p,c>>1))%mod * sum(p,(c-1)>>1)%mod + powmod(p,c))%mod;
}
void solve()
{
    ll a,b;
    scanf("%lld%lld",&a,&b);
    if(a==0) {puts("0"); return 0;}
    ll ans=1;

    rep(i,2,a+1) // 试除法分解质因数
    {
        int s=0;
        while(a%i==0)
        {
            s++;
            a/=i;
        }
        if(s) ans= ans %mod  * sum(i,s*b) %mod; 
    }
    printf("%lld\n",ans);
}
int main()
{
    solve();
}
posted @ 2020-05-29 11:32  Hyx'  阅读(139)  评论(0)    收藏  举报