POJ

来源:互联网 发布:linux sd卡自动挂载 编辑:程序博客网 时间:2024/06/07 10:03

题目链接:https://vjudge.net/problem/POJ-1845

题目大意:求A^B的所有因数和

解题思路:由约数和定理可以知道,A可以分解成p1^a1*p2^a2*……pk^ak,那么A^B为p1^(a1*B)*p2^(a2*B)……pk^(ak*B),那么因数和为(1+p1+p1^2+……+p1^(a1*b))……*(1+pk+pk^2+……+pk^(ak*b))

解法一:
对于1+p+p^2+……+p^n,当n为奇数时,等价于(1+p+…..p^(n/2))(p^(n/2+1)+1),当n为偶数时,等价于(1+p+…..p^(n/2))(p^(n/2+1)+1)-p^(n+1),所以可以用递归求解

AC代码:

#include<cstdio>#include<map>using namespace std;typedef long long LL;const int Mod = 9901;const int MAXN = 10000;bool vis[MAXN];int prime[MAXN], tot;map<int, int> mp;void toInit(){    tot = 0;    for (int i = 2;i < MAXN;i++)    {        if (!vis[i])            prime[tot++] = i;        for (int j = 0;j < tot&&prime[j] * i < MAXN;j++)        {            vis[prime[j] * i] = 1;            if (i%prime[j] == 0)                break;        }    }}void toDivide(int n){    for (int i = 0;i<tot&&prime[i] <= n;i++)    {        while (n%prime[i] == 0)            mp[prime[i]]++, n /= prime[i];    }    if (n > 1) mp[n]++;}LL quickMod(LL a, LL b){    a %= Mod;    LL ans = 1;    while (b)    {        if (b & 1) ans = ans*a%Mod;        a = a*a%Mod;        b >>= 1;    }    return ans;}LL toDfs(LL p,LL n){    if (n == 0) return 1;    LL ans=toDfs(p, n / 2)*(quickMod(p, n / 2 + 1) + 1) % Mod;    if (n % 2) return ans;    return ((ans - quickMod(p, n + 1)) % Mod + Mod) % Mod;}int main(){    toInit();    int a, b;scanf("%d%d", &a, &b);    toDivide(a);    LL ans = 1;    for (map<int, int>::iterator it = mp.begin();it != mp.end();it++)        ans *= toDfs(it->first, (it->second)*b), ans %= Mod;    printf("%I64d\n", ans);    return 0;}

解法二:
对于1+p+p^2+……+p^n,可以直接用等比数列求和公式得(p^(n+1)-1)/(p-1),对于形如(a/b)%m且b|a,这里介绍当b与m不互为素数时的处理方法,(a/b)%m=(a%(b*m))/b,快速幂乘积时会爆longlong,所以用快速乘处理

AC代码:

#include<cstdio>#include<map>using namespace std;typedef long long LL;const int Mod = 9901;const int MAXN = 10000;bool vis[MAXN];int prime[MAXN], tot;map<int, int> mp;void toInit(){    tot = 0;    for (int i = 2;i < MAXN;i++)    {        if (!vis[i])            prime[tot++] = i;        for (int j = 0;j < tot&&prime[j] * i < MAXN;j++)        {            vis[prime[j] * i] = 1;            if (i%prime[j] == 0)                break;        }    }}void toDivide(int n){    for (int i = 0;i<tot&&prime[i] <= n;i++)    {        while (n%prime[i] == 0)            mp[prime[i]]++, n /= prime[i];    }    if (n > 1) mp[n]++;}LL quickMul(LL a, LL b, LL m){    a %= m;    LL ans = 0;    while (b)    {        if (b & 1) ans = (ans + a) % m;        a = (a + a) % m;        b >>= 1;    }    return ans;}LL quickPow(LL a, LL b, LL m){    a %= m;    LL ans = 1;    while (b)    {        if (b & 1) ans = quickMul(ans, a, m);        a = quickMul(a, a, m);        b >>= 1;    }    return ans;}int main(){    toInit();    LL a, b;scanf("%I64d%I64d", &a, &b);    toDivide(a);    LL ans = 1;    for (map<int, int>::iterator it = mp.begin();it != mp.end();it++)    {        LL down = it->first - 1;        LL M = down*Mod;        LL up = (quickPow(it->first, it->second*b + 1, M) - 1 + M) % M;        ans *= (up / down);        ans %= Mod;    }    printf("%I64d\n", ans);    return 0;}
原创粉丝点击