LightOJ 1054 Efficient Pseudo Code(约数和)

题目链接: http://www.lightoj.com/volume_showproblem.php?problem=1054 

题意:求n^m的约数和。
思路:约数和的公式:设n=p1^n1*p2^n2*p3^n3*……pk^nk。那么n的所有约数和sum(n)=(p1^0+p1^1+……p1^n1)*……*(pk^0+pk^1+……pk^nk)。
#include <iostream>

#include <cmath>

#include <cstdio>

#define i64 long long

using namespace std;



const int MAX=70000;

int prime[MAX],tag[MAX],cnt;



void init()

{

    int i,j;

    for(i=2;i<MAX;i++) if(!tag[i])

    {

        prime[++cnt]=i;

        for(j=i+i;j<MAX;j+=i) tag[j]=1;

    }

}



const i64 MOD=1000000007;

int C,num=0;

i64 n,m;



//求n^m%mod

i64 POW(i64 n,i64 m,i64 mod)

{

    i64 ans=1;

    while(m)

    {

        if(m&1) ans=ans*n%mod;

        n=n*n%mod;

        m>>=1;

    }

    return ans;

}



//求(n^0+n^1+n^2+……n^m)%mod

i64 get(i64 n,i64 m,i64 mod)

{

    if(!m) return 1;

    i64 temp=POW(n,(m+1)>>1,mod)+1;

    if(m&1) return temp*get(n,m>>1,mod)%mod;

    return (POW(n,m,mod)+temp*get(n,(m-1)>>1,mod))%mod;

}



int main()

{

    init();

    for(scanf("%d",&C);C--;)

    {

        scanf("%lld%lld",&n,&m);

        i64 ans=1,i,p;

        for(i=1;i<=cnt&&prime[i]*prime[i]<=n;i++)

        {

            if(n%prime[i]==0)

            {

                p=0;

                while(n%prime[i]==0)

                {

                    p++;

                    n/=prime[i];

                }

                ans=ans*get(prime[i],p*m,MOD)%MOD;

            }

        }

        if(n>1) ans=ans*get(n,m,MOD)%MOD;

        printf("Case %d: %lld\n",++num,ans);

    }

    return 0;

}

  

你可能感兴趣的:(code)