【题解】约数之和

约数之和

题意

给定两个整数 \(A, B\)​​ ,求 \(A^B\)​​ 的约数之和 \(\bmod 9901\)​​​​。

\(0\leq A,B\leq5\times10^7\)

Solution

由唯一分解定理,设 \(A=p_1^{k_1}\times p_2^{k_2}\times...\times p_n^{k_n}\)​。

\(A\)​ 的约数总数为

\[(1+k_1)\times(1+k_2)\times...\times(1+k_n) \]

\(A\)​ 的约数总和为

\[(p_1^0+p_1^1+...+p_1^{k_1})(p_2^0+p_2^1+...+p_2^{k_2})(p_n^0+p_n^1+...+p_n^{k_n}) \]

\[\prod^n_{i=1}(\sum_{j=0}^{k_i}p_i^j) \]

直接算的复杂度大概为 \(O(n^2)\)​​ ,有T的可能。将求和部分用等比数列求和优化一下,再把 \(B\)​​ 次幂搞上,得到约数总和为

\[\prod^n_{i=1}(\frac{p^{Bk_i+1}-1}{p_i-1}) \]

分子用快速幂求。分母由于是模意义下,要求出其乘法逆元,注意到 \(9901\)​​ 是质数,可以用费马小定理求。

注意要特判一下 \(A=1\)​ 的情况。

时间复杂度主要在快速幂和枚举质因数上,分解质因数对复杂度无影响。复杂度(大概)是 \(O(n\log n)\)​。

Code

#include <bits/stdc++.h>
using namespace std;
const int mod = 9901;
typedef long long ll;
ll qpow(ll a, ll x)
{
    a %= mod;
    if (x == 1)
        return a;
    ll res = qpow(a, x / 2);
    if (x & 1)
        return res * res % mod * a % mod;
    else
        return res * res % mod;
}
ll ni(ll a) { return qpow(a, 9901 - 2); }
int A, B;
typedef pair<ll, ll> pii;
vector<pll> p;
int main()
{
    cin >> A >> B;
    if (A == 1)
    {
        cout << 1 << endl;
        return 0;
    }
    int i;
    for (i = 2; i <= A; i++)
    {
        int sum = 0;
        while (A % i == 0)
            A /= i, sum++;
        if (sum)
            p.push_back(pii(i, sum));
    }
    ll ans = 1;
    for (int i = 0; i < p.size(); i++)
    {
        ans *= ((qpow(p[i].first, B * p[i].second + 1) - 1) % mod * ni(p[i].first - 1) % mod) % mod;
        ans %= mod;
    }
    cout << ans << endl;
    return 0;
}

posted @ 2021-07-23 15:40  _slb  阅读(102)  评论(0编辑  收藏  举报