• 97.约数之和


    原题链接:97. 约数之和

    解题思路

    根据乘法分配律,AB的所有约数之和为:

    (1+p1+p12+...+p1BxC1)x(1+p2+p22+...+p2BxC2)x...x(1+pn+pn2+...+pnBxCn)

    我们把改式展开,与约数集合比较。
    上式中的每个括号内都是等比数列,如果使用等比数列求和公式,需要做除法。而答案还要对9901取模,mod运算只对加、减、乘有分配律,不能直接对分子,分母分别取模后再做除法,我们可以换一种思路,使用分治法进行等比数列求和。

    问题:使用分治法求sum(p,c)=1+p+p2+...+pc=?
    若c为奇数:

    sum(p,c)=(1+p+...+p(c-1)/2)+(p(c+1)/2+...+pc)
    =(1+p+...+p(c-1)/2)+p(c+1)/2x(1+p+...+p(c-1)/2)
    =(1+p(c+1)/2) x sum(p,(c-1)/2)

    若c为偶数,类似的:
    sum(p,c)=(1+pc/2) x sum(p,(c/2)-1) + pc

    每次分治(递归之后),问题的规模会缩小一半,配合快速幂即可在O(logc)的时间内求出等比数列的和。

    样例代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    #define Mod 9901
    int a,b;
    int ksm(int a,int b)//快速幂函数
    {
        int ans=1;
        a%=Mod;
        while(b)
        {
            if (b&1)
                ans=ans%Mod*a;
            a=a%Mod*a%Mod;
            b>>=1;
        }
        return ans;
    }
    long long sum(int p,int c)
    {
        if (c==0)
            return 1;
        if(c&1)
            return ((1+ksm(p,(c+1)>>1))*sum(p,(c-1)>>1))%Mod;//奇数的情况下
        else
            return ((1+ksm(p,c>>1))*sum(p,(c>>1)-1)+ksm(p,c))%Mod;//偶数的情况下
    }
    int main()
    {
        cin>>a>>b;
        int ans=1;
        for (int i=2;i<=a;i++)
        {
            int s=0;
            while(a%i==0)
            {
                s++;
                a/=i;
            }
            if (s)//这句话剪枝.然后就TLE变成了AC.by POJ
                ans=ans*sum(i,s*b)%Mod;
        } 
        if (a==0)
            cout<<0<<endl;//特判的情况,这里非常的阴毒,出题人用心险恶
        else
            cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    TortoiseGit日常使用指南
    Ajax在MVC中的应用
    STL源码学习内存管理
    功能最强大的.Net代码生成器——EasyCode
    TortoiseGit使用入门
    负载均衡时数据包流程详解
    C++异步编程 for VS2011
    (译)一个通用快速的反射方法调用
    移位运算
    使用Autofac在ASP.NET Web API上实现依赖注入
  • 原文地址:https://www.cnblogs.com/hnkjdx-ssf/p/14156424.html
Copyright © 2020-2023  润新知