Cod sursa(job #3319657)

Utilizator gicaviitorulgica viitorul gicaviitorul Data 2 noiembrie 2025 13:29:22
Problema Suma divizorilor Scor 80
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.38 kb
#include <bits/stdc++.h>
using namespace std;

#define int unsigned long long
const int MOD = 9901;

int expmod(int a, int k)
{
    a %= MOD;                  // reduc baza din start
    int p = 1;
    while (k > 0)
    {
        if (k & 1)
            p = (int)((__int128)p * a % MOD);   // protejeaza produsul
        a = (int)((__int128)a * a % MOD);       // protejeaza produsul
        k >>= 1;
    }
    return p;
}

int inv_mod(int a)
{
    a %= MOD;
    if (a < 0) a += MOD;
    // MOD e prim, deci inversul este a^(MOD-2)
    return expmod(a, MOD - 2);
}

// calculeaza suma divizorilor lui a^b modulo MOD
int sumdiv(int a, int b)
{
    if (a == 0) {
        // Suma divizorilor lui 0 nu e definita; trateaza dupa cerinta problemei.
        // Aici returnam 0 ca fallback.
        return 0;
    }
    if (a == 1) {
        // 1^b = 1 => suma divizorilor = 1
        return 1;
    }

    // factorizam a
    vector<pair<int,int>> f;
    int n = a;
    for (int divv = 2; (__int128)divv * divv <= n; ++divv)
    {
        if (n % divv == 0)
        {
            int put = 0;
            while (n % divv == 0) {
                n /= divv;
                ++put;
            }
            f.push_back({divv, put});
        }
    }
    if (n > 1) f.push_back({n, 1}); // factor prim ramas

    // produsul pe factori: (p^{e*b+1} - 1) / (p - 1)
    int allput = 1;

    // putem reduce exponentul modulo (MOD-1) (teorema lui Fermat), deoarece gcd(p, MOD) = 1
    const int EXP_MOD = MOD - 1;

    for (auto &it : f)
    {
        int p = it.first;
        int e = it.second;

        // exponent = e*b + 1, redus modulo (MOD-1)
        int eb = (int)((__int128)e * b % EXP_MOD);
        int exp_total = (eb + 1) % EXP_MOD;

        int num = expmod((int)(p % MOD), exp_total);   // p^{e*b+1} mod MOD
        num = (num + MOD - 1) % MOD;                   // (p^{...} - 1) mod MOD

        int den = (int)((p % MOD + MOD) % MOD);
        den = (den + MOD - 1) % MOD;                   // (p - 1) mod MOD
        // den nu poate fi 0 aici (p != MOD), dar oricum folosim inv_mod
        int inv = inv_mod(den);

        allput = (int)(((__int128)allput * num) % MOD);
        allput = (int)(((__int128)allput * inv) % MOD);
    }

    return allput;
}

signed main()
{
    ifstream cin("sumdiv.in");
    ofstream cout("sumdiv.out");

    int a, b;
    cin >> a >> b;

    // Suma divizorilor lui a^b (mod MOD)
    cout << sumdiv(a, b);
}