LightOj1054

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

题意:给你两个数n和m, 求n^m的所有因子和,结果对1000000007求余;(n和m在int范围内)

 和求因子个数有一定的关系,一个数 n 可以表示成 n = p1^a1 * p2^a2 * p3^a3 * ... pk^ak,(其中pi是n的素因子)

那么n的因子和就是 (p1^0+p1^1+p1^2+...+p1^a1)*(p2^0+p2^1+p2^2+...+p2^a2)*...*(pk^0+pk^1+...+pk^ak);

至于为什么可以把这些拆开来想就好了;所以对于每一项我们要求等比数列的和,还有就是除法求余问题运用公式 a/b%mod = a*b^(mod-2);

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
typedef long long LL;
#define N 100005
using namespace std;
const double eps = 1e-6;
const LL mod = 1000000007;

int f[N], p[N], k = 0;
void Prime()
{
    for(int i=2; i<N; i++)
    {
        if(!f[i]) p[k++] = i;
        for(int j=i; j<N; j+=i)
            f[j] = 1;
    }
}

LL Pow(LL a, LL b)/// Calculate: a^b%mod;
{
    LL ans = 1;
    while(b)
    {
        if(b&1) ans = ans*a%mod;
        a = a*a%mod;
        b >>= 1;
    }
    return ans;
}
///a/b%mod = a*b^(mod-2)%mod;
LL Sn(LL q, LL n)/// Calculate: (q^n-1)/(q-1)%mod;
{
    LL ans = Pow(q, n);
    ans = (ans-1) * Pow(q-1, mod-2) % mod;
    return (ans+mod)%mod;///因为上面出现了-1所以可能变成负数;
}

int main()
{
    Prime();

    int T, t = 1;

    LL n, m;

    scanf("%d", &T);

    while(T--)
    {
        scanf("%lld %lld", &n, &m);

        LL ans = 1;

        for(int i=0; i<k && (LL)p[i]*p[i]<=n; i++)
        {
            if(n%p[i])continue;
            LL cnt = 0;

            while(n%p[i] == 0)
            {
                cnt ++;
                n /= p[i];
            }

            cnt = cnt*m+1;

            LL ret = Sn(p[i], cnt);

            ans = ans*ret%mod;
        }
        if(n>1)
            ans = ans*Sn(n, m+1)%mod;

        printf("Case %d: %lld
", t++, ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5996515.html