POJ1845 Sumdiv

原题面:https://vjudge.net/problem/POJ-1845

题目大意:求pow(A,B)的所有约数之和mod9901(1<=A,B<=5e7)。

输入描述:一行两个正整数A(1<=A<=5e7),B(1<=B<=5e7)。

输出描述:输出pow(A,B)所有约数之和mod9901。

样例输入:

2 3

样例输出:

15

分析:把A分解质因数可得A=pow(p1,c1)pow(p2,c2)...pow(pn,cn)。故pow(A,B)的所有约数之和为(1+p1+pow(p1,2)+...+pow(p1,c1))(1+p2+pow(p2,2)+...+pow(p2,c2))...(1+pn+pow(pn,2)+...pow(pn,cn))。可以看出每个部分都是一个等比数列,运用等比数列求和公式即可求出每部分的值,最后相乘取模即为答案。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=40;
const ll mod=9901;
ll p[maxn],c[maxn],m;
void divide(int n) {
    m = 0;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            p[++m] = i;
            c[m] = 0;
            while (n % i == 0) n /= i, c[m]++;
        }
    }
    if (n > 1) p[++m] = n, c[m] = 1;
}
ll power(ll a,ll b) {
    ll ret = 1;
    while (b) {
        if (b & 1)
            ret = (ret * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return ret;
}
ll inv(ll a) {
    return power(a, mod - 2);
}
int main() {
    ll a, b;
    cin >> a >> b;
    divide(a);
    ll ret = 1;
    for (int k = 1; k <= m; k++) {
        if ((p[k] - 1 + mod) % mod == 0) {
            ret = (ret * ((b * c[k] + 1) % mod)) % mod;
            continue;
        }
        ret = (ret * (power(p[k], (ll) b * c[k] + 1) - 1 + mod) % mod) * inv(p[k] - 1) % mod;
    }
    cout << ret << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/SwiftAC/p/12110786.html