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

整理的算法模板:ACM算法模板总结(分类详细版)

假设现在有两个自然数A和B,S是ABAB的所有约数之和。

请你求出S mod 9901的值是多少。

输入格式

在一行中输入用空格隔开的两个整数A和B。

输出格式

输出一个整数,代表S mod 9901的值。

数据范围

0≤A,B≤5×1070≤A,B≤5×107

输入样例:

2 3

输出样例:

15

注意: A和B不会同时为0。

 

用到知识点  :

  • 分解质因数求约数之和
  • 数列求和(递归法)

对一个数分解质因数并记录次数:

如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)

所以A的B次方的所有约数之和为

怎样用递归求每一个括号里面的值呢(先不算+1)?

当k是偶数时,提取公因数变成(1+p^{k/2})* sum(p , k/2);

当k是奇数时,同样对最后一项单独计算,前面k-1项时偶数,递归即可;quick(p , k / 2) + sum (p , k / 2);

递归即可;

#include 
using namespace std;
typedef long long ll;
const int mod=9901;
ll quick(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(ll p,ll k)
{
    if(k==0) return 0;
    if(k==1) return p;
    if(k&1) return quick(p,k)%mod+sum(p,k-1)%mod;
    else return (1+quick(p,k/2))%mod*sum(p,k/2)%mod;
}
int main()
{
    int a,b;
    cin >>a>>b;
    ll ans=1;
    if(a==0) ans=0;

    for(int i=2;i*i<=a;i++)
    {
        if(a%i==0)
        {
            ll cnt=0;
            while(a%i==0) a/=i,cnt++;
            ans=ans*(sum(i,b*cnt)%mod+1)%mod;
        }
    }
    if(a>1) ans=ans*(sum(a,b)%mod+1);
    cout <

 

 

你可能感兴趣的:(基础算法——数论,#,分治)