Sumdiv
Explicación
Para un entero , la suma de todos los divisores de se puede calcular de forma eficiente usando la función de divisores .
La fórmula establece que si es la factorización prima de , entonces la suma de los divisores es:
En este problema necesitamos calcular la suma de divisores de . Si la factorización prima de es entonces la factorización prima de será y podemos calcular la suma de divisores usando la fórmula de arriba, .
Si , entonces podemos calcular el valor de la expresión usando exponenciación modular e inverso modular. En caso contrario, la expresión vale .
Sí necesitamos calcular los factores primos de , pero afortunadamente esto se puede hacer en tiempo .
Como puede ser tan grande como , para evitar desbordamientos podemos usar la función de Euler y exponenciación binaria para calcular las potencias módulo .
Implementación
Complejidad temporal:
#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';
}
}