Skip to Content

Sumdiv

Explicación

Para un entero AA, la suma de todos los divisores de AA se puede calcular de forma eficiente usando la función de divisores .

La fórmula establece que si d1p1d2p2...dkpkd_1^{p_1} \cdot d_2^{p_2} \cdot ... \cdot d_k^{p_k} es la factorización prima de AA, entonces la suma de los divisores es:

S=i=1kdipi+11di1. S = \prod_{i=1}^{k}\frac{d_i^{p_i+1} - 1}{d_i -1}.

En este problema necesitamos calcular la suma de divisores de ABA^B. Si la factorización prima de AA es d1p1d2p2...dkpkd_1^{p_1} \cdot d_2^{p_2} \cdot ... \cdot d_k^{p_k} entonces la factorización prima de ABA^B será d1Bp1d2Bp2...dkBpkd_1^{B\cdot p_1} \cdot d_2^{B\cdot p_2} \cdot ... \cdot d_k^{B\cdot p_k} y podemos calcular la suma de divisores usando la fórmula de arriba, S=i=1kdiBpi+11di1S = \prod_{i=1}^{k}\frac{d_i^{B\cdot p_i+1} - 1}{d_i -1}.

Si di≢1(mod109+7)d_i\not \equiv 1 \pmod{10^9+7}, entonces podemos calcular el valor de la expresión diBpi+11di1(mod109+7)\frac{d_i^{B\cdot p_i+1} - 1}{d_i -1}\pmod{10^9+7} usando exponenciación modular e inverso modular. En caso contrario, la expresión vale 1+di+di2+...+diBpiBpi+1(mod109+7)1+d_i + d_i^2 + ... + d_i^{B\cdot p_i}\equiv B\cdot p_i+1\pmod{10^9+7}.

Sí necesitamos calcular los factores primos de AA, pero afortunadamente esto se puede hacer en tiempo O(A)\mathcal{O}(\sqrt{A}).

Como BB puede ser tan grande como 101810^{18}, para evitar desbordamientos podemos usar la función φ\varphi de Euler y exponenciación binaria para calcular las potencias módulo 109+710^9+7.

Implementación

Complejidad temporal: O(A+logAlogB)\mathcal{O}(\sqrt{A}+\log A\cdot \log B)

#include <fstream> using namespace std; #define ll long long const int MOD = 1e9 + 7; // BeginCodeSnip{Binary Exponentiation} ll pow(ll a, ll b, ll m) { ll res = 1; a %= m; // para evitar desbordamientos cuando a > 1e9 while (b) { if (b & 1) { res = (res * a) % m; } a = (a * a) % m; b /= 2; } return res; } // EndCodeSnip int main() { ifstream fin("sumdiv.in"); ll a, b; fin >> a >> b; ofstream fout("sumdiv.out"); if (b == 0) { fout << '1' << '\n'; // a^0 = 1 } else { ll ans = 1; for (ll i = 2; i * i <= a; i++) { if (a % i == 0) { // si i divide a entonces en este caso siempre es primo // hallamos la potencia máxima de i que divide a a. ll co = 0; while (a % i == 0) { co++; a /= i; } // hallamos el valor de d - 1 y (d^k - 1) módulo (10^9 + 7). ll d_1 = pow(i - 1, MOD - 2, MOD); ll dk_1 = (pow(i, (co * (b % (MOD - 1)) + 1) % (MOD - 1), MOD) - 1 + MOD) % MOD; ans = (ans * ((d_1 * dk_1) % MOD)) % MOD; } } if (a > 1 && ((a - 1) % MOD) != 0) { // si a es mayor que 1 y a - 1 no es divisible por 10^9 + 7 // hallamos el valor de d - 1 y (d^k - 1) módulo (10^9 + 7). ll d_1 = pow(a - 1, MOD - 2, MOD); ll dk_1 = (pow(a, (b + 1) % (MOD - 1), MOD) - 1 + MOD) % MOD; ans = (ans * ((d_1 * dk_1) % MOD)) % MOD; } else if (a > 1) { /* * si a - 1 es divisible por 10^9 + 7, * a es un primo de la forma k * (10^9 + 7) + 1. * esto significa que la suma de a^i módulo (10^9 + 7), donde i va de 0 a b * es (b + 1), así que multiplicamos por (b + 1). */ ans = (ans * ((b + 1) % MOD)) % MOD; } fout << ans << '\n'; } }