2023.04.14 定时测试随笔 T2

T2 P1593 因子和

传送门:洛谷P1593

既然要求因子和,那我们就先对 \(a\) 分解质因数,得:

              \(a = p_1^{k_1} + p_2^{k_2} + p_3^{k_3}... + p_n^{k_n}\)

所以 \(a^b\) 质因数分解就会得到:

              \(a^b = p_1^{k_1*b} + p_2^{k_2*b} + p_3^{k_3*b}... + p_n^{k_n*b}\)

接下来,就是对所有因子求和:

\(ans = (1+p_1^1+p_2^2+p_3^3...p_1^{k_1*b})(1+p_2^1+p_2^2+p_2^3...p_2^{k_2*b})....(1+p_n^1+p_n^2+p_n^3...p_n^{k_n*b})\)

对于上面这个式子,每一个乘数都是一个等比数列,根据等比数列求和公式:

               \(sum = \frac{p^n - 1}{p - 1}\)

我们可以用快速幂求出 \(p^n-1\) 因为要对 \(9901\) 取模,所以我们要求 \(p - 1\) 得逆元,\(9901\)是质数,可以用费马小定理求,\(x^{-1} = pow(x, mod - 2)\);

还有一种特殊情况:

  • \(p-1\) \(mod\) \(9901 == 0\) 那么 \(p\) \(mod\) \(9901 == 1\),所以 \(sum = 1 + p_1^1 mod9901 + p_2^2mod9901 + ...= 1 + n\)

贴代码:

#include <bits/stdc++.h>

typedef long long ll;
using namespace std;

const int maxn = 5e7 + 5;
const int modl = 9901;
ll p[maxn], k[maxn];
int a, b, cnt;
void Pre() {
    int x = a;
    for (int i = 2; i <= sqrt(x); ++ i) {
        if (x % i) continue ;
        p[++ cnt] = i;
        while (x % i == 0) {
            k[cnt] ++, x /= i;
        }
    }
    if (x != 1) {
        p[++ cnt] = x;
        k[cnt] ++;
    }
}

ll poww(ll a, ll b) {
    ll tot = 1;
    while (b) {
        if (b & 1) tot = a * tot % modl;
        a = a * a % modl;
        b >>= 1;
    }
    return tot;
}

void read() {
    scanf("%d%d", &a, &b);
    if (!a) {
        printf("0\n");
        return ;
    }
    Pre();
    ll ans = 1, sum = 0;
    for (int i = 1; i <= cnt; ++ i) {
        k[i] *= b;
        if ((p[i] - 1) % modl == 0) {
            sum = (k[i] + 1) % modl;
        }
        else {
            ll x = poww(p[i], k[i] + 1) - 1;//如果a等于9901,-1之后会是-1;
            ll y = poww(p[i] - 1, modl - 2);
            sum = x * y % modl;
        }
        ans = (ans * sum) % modl;
    }
    printf("%lld\n", (ans + modl) + modl);//ans有可能是负数;
}

int main() {
    read();
    return 0;
}
posted @ 2023-04-14 20:24  florence25  阅读(49)  评论(0)    收藏  举报