zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    病毒软件测试代码
    如何将WIN安全设置重置回默认值
    今天值班非常不爽。
    FTP命令(2)
    WORD操作
    DELPHI事务
    DELPHI一些常用的技巧
    钩子学习心得
    (转 )Delphi指针如何指向使用with开域语句创建的无名组件对象
    WebBrowser 操作记要 (DELPHI)
  • 原文地址:https://www.cnblogs.com/hnkjdx-ssf/p/14156424.html
Copyright © 2011-2022 走看看