[lnsyoj509/AcWing99]约数之和

题意

原题链接
\(A^B\)的约数之和\(\bmod 9901\)

sol

\(x\)的约数之和\(f(x)\)可以通过以下公式计算
根据算数基本定理,将\(x\)分解为$$\prod_{i=1}^k a_i^{p_i}$$
则$$f(x)=\prod_{i=1}^k \sum_{j=0}^{p_i} a_i^j = \prod_{i=1}^k \frac{a_i^{p_i+1} - 1}{a_i - 1}$$

证明

根据算数基本定理,将\(x\)分解为\(\prod_{i=1}^k a_i^{p_i}\)
易知\(a_i^{p_i}\)的所有约数为\(a_i^0,a_i^1,a_i^2,...,a_i^{p_i}\),共\(p_i+1\)个,每一个\(a_i^{p_i}\)的约数中选择一项并相乘,可以构成\(x\)的所有约数,因此,\(x\)的约数之和即为每一个\(a_i^{p_i}\)的所有约数之和的积。显然,\(a_i^{p_i}\)的值为等比数列,它们的和为\(\frac{a_i^{p_i+1} - 1}{a_i - 1}\),所以\(x\)的约数之和为\(\prod_{i=1}^k \frac{a_i^{p_i+1} - 1}{a_i - 1}\),即得证

至于分解\(A^B\),可以先对\(A\)进行质因数分解,则

\[A^B = (\prod_{i=1}^k a_i^{p_i})^B = \prod_{i=1}^k a_i^{p_i \cdot B} \]

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define x first
#define y second

using namespace std;
typedef pair<int, int> PII;

const int mod = 9901;

vector<PII> primes;
int a, b;

void div(int x){
    for (int i = 2; i <= x / i; i ++ ){
        if (x % i == 0){
            int cnt = 0;
            while (x % i == 0){
                x /= i;
                cnt ++ ;
            }
            primes.push_back({i, cnt});
        }
    }
    if (x != 1) primes.push_back({x, 1});
}

int qpow(int a, int k){
    int ans = 1;
    while (k){
        if (k & 1) ans = (long long) ans * a % mod;
        a = (long long) a * a % mod;
        k >>= 1;
    }
    return ans;
}

int main(){
    scanf("%d%d", &a, &b);
    div(a);
    long long ans = 1;
    for (auto p : primes){
        int m = qpow(p.x - 1, mod - 2); //计算逆元
        ans = ans * (qpow(p.x, p.y * b + 1) - 1) % mod * m % mod;
    }

    printf("%lld\n", ans);

    return 0;
}
posted @ 2024-06-15 22:37  是一只小蒟蒻呀  阅读(10)  评论(0编辑  收藏  举报