lightoj 1054 - Efficient Pseudo Code 求所有n^m的所有因子和

题意:求n^m的所有因子和。

题解:我们需要先知道,一个数X=p1^t1*p2^t2*...*pk^tk(pi为素数),还需要知道X的所有因子和sum(X)=(p1^0+p1^1+...+p1^t1)*...*(pk^0+pk^1+...+pk^tk)。证明略,以前证明过,可以自己在我其他文中找下,好像那题跟这题一样,就是因子都是排列组合ti得到的。所以结果就很简单了,n^m=p1^(t1*m)*...pk^(tk^m);还需要筛选下素数,和快速幂以及等比数列求和,还有除法取余(这个就是逆元和费马定理:a/b%mod=a*b^(mod-2)%mod)。




#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const int mod=1e9+7;
const int maxn=1e5+10;
LL prime[maxn],vis[maxn],t;
void init()
{
    LL i,j,k,m;
    t=0;
    m=(LL)sqrt(maxn+0.5);
    memset(vis,0,sizeof(vis));
    for(i=2;i<=m;i++)
    {
        if(!vis[i])
        for(j=i*i;j<maxn;j+=i)
        vis[j]=1;
    }
    for(i=2;i<maxn;i++)
    if(!vis[i])prime[t++]=i;
}
LL pow_mod(LL a,LL b)
{
    LL s=1;
    while(b)
    {
        if(b&1)s=(s*a)%mod;
        a=(a*a)%mod;
        b=b>>1;
    }
    return s;
}
LL find(LL a,LL b)
{
    LL ans;

    ans=pow_mod(a,b)-1;
    ans=ans*pow_mod(a-1,mod-2)%mod;
    ans=(ans+mod)%mod;
    return ans;
}
int main()
{
    init();
    LL n,m,T,tt=0;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&m);
        LL i,j,k,num;
        LL ans=1;
        for(i=0;i<t&&prime[i]*prime[i]<=n;i++)
        {
            if(n%prime[i]==0)
            {
                num=0;
                while(n%prime[i]==0){n=n/prime[i];num++;}
                //cout<<find(prime[i],m*num+1)<<endl;
                ans=ans*find(prime[i],m*num+1)%mod;
            }
        }
        if(n>1)
        ans=ans*find(n,m+1)%mod;
        printf("Case %lld: %lld\n",++tt,ans);
    }
    return 0;
}


你可能感兴趣的:(lightoj 1054 - Efficient Pseudo Code 求所有n^m的所有因子和)