AcWing 97.约数之和 (约数定理)

题目:约数之和

题意:

求 A^B的约数之和对9901取模的答案,A,B在[0, 5 1 0 7 5*10^7 ]中,A,B不能同时为0

题解:

约数之和定理:

证明:
首先我们可知一个数 A 可以拆分为: A = p 1 a p 2 b . . . . . p n c A=p1^a*p2^b.....*pn^c ,( p p 代表质数)
A A 的约数个数为 ( a + 1 ) ( b + 1 ) . . . . ( c + 1 ) (a+1)*(b+1)....*(c+1)
由乘法分配律: s u m ( A ) = ( p 1 0 + p 1 1 + . . . . . p 1 a ) ( p 2 0 + p 2 1 + . . . . . p 2 b ) . . . . . . . ( p n 0 + p n 1 + . . . . . p n c ) sum(A)=(p1^0+p1^1+.....p1^a)*(p2^0+p2^1+.....p2^b).......*(pn^0+pn^1+.....pn^c)

优化:
对于 A A 的一个 p p 的所有约数和,我们可以用递归来实现,但是时间复杂度太高,所以我们需要对递归进行优化,使其变成 O ( l o g n ) O(logn)
当k是奇数:
s u m ( p , k ) = ( p 0 + p 1 + . . . . . p k ) = ( p 0 + . . . . p k / 2 ) + ( p k / 2 + 1 . . . . . + p k ) = ( p 0 + . . . . p k / 2 ) + p k / 2 + 1 ( p 0 + . . . . p k / 2 ) = ( 1 + p k / 2 + 1 ) s u m ( p , k / 2 ) sum(p,k)=(p^0+p^1+.....p^k)=(p^0+....p^{k/2})+(p^{k/2+1}.....+p^k)=(p^0+....p^ {k/2})+p^{k/2+1}*(p^0+....p^{k/2})=(1+p^{k/2+1})*sum(p,k/2)

当k是偶数时,我们可以按照一般的递归方式写即可,时间复杂度依然为 O ( l o g n ) O(logn)

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mod 9901
const int maxn=1e5+5;
ll ksm(ll a,ll b)
{
    ll res=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            res=(a%mod)*(res%mod)%mod;
        a=(a%mod)*(a%mod)%mod;
        b>>=1;
    }
    return res%mod;
}
ll sum(ll a,ll b)
{
    if(b==0)
        return 1;
    if(b&1)
        return (1+ksm(a,(b>>1)+1))*sum(a,b>>1)%mod;
    else
        return (ksm(a,b)+sum(a,b-1)%mod)%mod;
}
void solv(ll x,ll b)
{
    ll res=1;
    for(int i=2;i<=x;i++)
    {
        int s=0;
        while(x%i==0)
        {
            s++;
            x/=i;
        }
        if(s)
            res=(res%mod)*(sum(i,s*b)%mod)%mod;
    }
    cout<<res%mod<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll a,b;
    cin>>a>>b;
    if(a==0)
        cout<<0<<endl;
    else
    solv(a,b);
}

  
发布了254 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/yangzijiangac/article/details/105082659
今日推荐