• 【Luogu】P1593因子和(唯一分解定理,约数和公式)


    题目链接

    首先介绍两个定理。

    整数唯一分解定理:任意正整数都有且只有一种方式写出素数因子的乘积表达式。

    (A=(p1k1 p2k2 ...... pnkn )

    求这些因子的代码如下

    for(int i=2;i*i<=a;++i){
            if(!(a%i)){
                prime[++num]=i;
                while(!(a%i)){
                    a/=i;
                    sum[num]++;
                }
            }
        }
        if(a!=1){
            prime[++num]=a;
            sum[num]=1;
        }
    唯一分解定理

    约数和公式:对于已经分解的整数A,有A的所有因子和为

    ( S= (1+p1+p12+p13+......+p1k1) (1+p2+p22+p23+......+p2k2)........(1+pn+pn2+pn3+......+pnkn) )

    所以局势明朗。用快速幂求出p的k*b次方,然后递归求和。代码如下

    long long Sum(long long p,long long n){
        if(n==0)    return 1;
        if(n&1)    return (Sum(p,n>>1)*(1+Pow(p,(n>>1)+1)))%mod;
        return     (Sum(p,(n>>1)-1)*(1+Pow(p,(n>>1)+1))+Pow(p,n>>1))%mod;
    }

    解题代码如下

    #include<cstdio>
    #include<cctype>
    #define mod 9901
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int prime[10000];
    int sum[10000];
    int num;
    
    long long Pow(long long n,long long i){
        if(i==0)    return 1;
        if(i==1)    return n%mod;
        long long ret=Pow(n,i>>1);
        if(i&1)    return (((ret*ret)%mod)*n)%mod;
        return (ret*ret)%mod;
    }
    
    long long Sum(long long p,long long n){
        if(n==0)    return 1;
        if(n&1)    return (Sum(p,n>>1)*(1+Pow(p,(n>>1)+1)))%mod;
        return     (Sum(p,(n>>1)-1)*(1+Pow(p,(n>>1)+1))+Pow(p,n>>1))%mod;
    }
    
    int main(){
        long long a=read(),b=read();
        for(int i=2;i*i<=a;++i){
            if(!(a%i)){
                prime[++num]=i;
                while(!(a%i)){
                    a/=i;
                    sum[num]++;
                }
            }
        }
        if(a!=1){
            prime[++num]=a;
            sum[num]=1;
        }
        int ans=1;
        for(int i=1;i<=num;++i)
            ans=(ans*Sum(prime[i],sum[i]*b)%mod)%mod;
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Visual Studio 2008 菜单:工具+选项+文本编辑器+HTML+格式,选中“键入时插入属性值引号”
    itemarray的意思
    SQL技巧大全
    IIS调用com组件的权限问题
    网站快速备案法(1小时)
    ASP.NET 2.0中WEB应用程序的部署
    c#中MessageBox的使用
    推荐一款DataGridView的打印解决方案
    使用C#格式化字符串
    关于MSSQL导入导出时主键与约束丢失的问题解决
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/7483285.html
Copyright © 2020-2023  润新知