acwing 97.约数之和(递归 分治 数论)

核心思想:分治递归
//A=p1^k1+p2^k2+...+pn^kn 分解质因数
//推广: A^B=p1^(k1*B)+p2^(k2^B)+...+pn^(kn*B)
//约数之和:
//1. (p1^0+p1^1+...+p1^(k1*B))*(p2^0+p2^1+...+p2^(k2^B)*...*(pn^0+pn^1+...+pn^(k2*B))
//可以理解为:()+()+...+()
//以上每个括号为式子1里每个大括号里随机挑选一个数的乘积
//例如(p1^0*p2^2*...*pn^4) 这样随机相乘的结果一定是约数
//把所有约数这样累加起来,便是约数和
//分治递归优化
//如果k是偶数,则有奇数个数
//sum(a,k)=sum(a,k-1)*a+1
//如果k是奇数,则有偶数个数
//sum(a,k)=(1+a^1+a^2+a^3+...+a^k)
//        =(1+a^1+...+a^(k/2))+a^(k/2+1)*(1+a^1+..+a^(k/2)) 
//          解释:k为奇数,k/2会向下取整,最终a^k=(a^(k/2)*a^(k/2+1))
//        =sum(a,k/2)*(1+a^(k/2+1));

ac代码:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int mod=9901;
typedef long long LL;
int a,b;
LL res=1;
LL qmi(int a,int b)
{
    LL ans = 1;
    while(b)
    {
        if(b&1) ans=(LL)ans*a%mod;
        a=(LL)a*a%mod;
        b>>=1;
    }
    return ans%mod;
}
int sum(int a,int k)
{
    if(k==0) return 1;
    if(k%2==0)
    {
        return (sum(a,k-1)*(a%mod)+1)%mod;
    }
    return (sum(a,k/2)*(1+qmi(a,k/2+1)))%mod;
}
int main()
{
    cin>>a>>b;

     //分解质因数
    for(int i=2;i<=a;i++)
    {
        int s=0;
        while(a%i==0)
        {
            s++;
            a/=i;
        }
        if(s) res=res*sum(i,s*b)%mod;
        //(p1^0+p1^1+...+p1^(k1*B))*(p2^0+p2^1+...+p2^(k2^B)*...*(pn^0+pn^1+...+pn^(k2*B))
    }
    if(!a) cout<<0;//需要特判,a是否为0
    else cout<<res;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值