Skip to Content

Divisor Analysis

Complejidad temporal: O(Nlog(max(ki)))\mathcal O(N \log(\max(k_i))).

Cantidad de divisores

Cada divisor del número se puede escribir como i=1Nxiαi\prod_{i = 1}^N x_i^{\alpha_i} donde 0αiki0 \leq \alpha_i \leq k_i.

Como hay ki+1k_i + 1 elecciones para αi\alpha_i, la cantidad de divisores es simplemente i=1N(ki+1)\prod_{i = 1}^N (k_i + 1).

Podemos calcular esto recorriendo los factores primos en tiempo O(N)\mathcal O(N).

Suma de divisores

Sea SiS_i la suma de divisores considerando solo los primeros ii factores primos. La respuesta será SNS_N.

Si=Si1j=0kixij=Si1xiki+11xi1 \begin{aligned} S_i &= S_{i - 1} \sum_{j = 0}^{k_i} x_i^j\\ &= S_{i - 1} \cdot \frac{x_i^{k_i + 1} - 1}{x_i - 1}\\ \end{aligned}

Podemos calcular cada SiS_i usando exponenciación rápida e inversos modulares en tiempo O(Nlog(max(ki)))\mathcal O(N \log(\max(k_i))).

Producto de divisores

Sean PiP_i y CiC_i el producto y la cantidad de divisores considerando solo los primeros ii factores primos, respectivamente. La respuesta será PNP_N.

Pi=Pi1ki+1(xiki(ki+1)/2)Ci1 \begin{aligned} P_i &= P_{i - 1}^{k_i + 1} \left(x_i^{k_i(k_i + 1)/2} \right)^{C_{i - 1}} \end{aligned}

De nuevo, podemos calcular cada PiP_i usando exponenciación rápida en tiempo O(Nlog(max(ki)))\mathcal O(N \log(\max(k_i))), ¡pero hay un detalle! Puede ser tentador usar Ci1C_{i - 1} de los valores calculados previamente en la parte 1 de este problema, pero esos valores van a dar respuestas incorrectas.

Esto es porque ab≢abmodp(modp)a^b \not \equiv a^{b \bmod p} \pmod{p} en general. Sin embargo, por el pequeño teorema de Fermat, ababmod(p1)(modp)a^b \equiv a^{b \bmod (p - 1)} \pmod{p} para pp primo, así que podemos guardar CiC_i módulo 109+610^9 + 6 para calcular PiP_i.

¿Cómo obtenemos esta recurrencia?

Claramente

P1=x10x11x12x1k1=x1k1(k1+1)2P_1 = x_1^0x_1^1x_1^2\dots x_1^{k_1} = x_1^\frac{k_1(k_1+1)}{2}

porque todos los xix_i son primos. Luego para P2P_2, tenemos

P2=x11×x12×x13××x1k1×x2×x2x1×x2x12××x2x1k1×x22×x22x1×x22x12××x22x1k1×x2k2×x2k2x1×x2k2x12××x2k2x1k1=P1×P1x2k1+1×P1(x2k1+1)2××P1(x2k1+1)k2=j=0k2(P1(x2k1+1)j). \begin{aligned} P_2 & = x_1^1\times x_1^2\times x_1^3\times\dots\times x_1^{k_1} \\ & \times x_2 \times x_2x_1 \times x_2x_1^2\times\dots\times x_2x_1^{k_1} \\ & \times x_2^2 \times x_2^2x_1 \times x_2^2x_1^2\times\dots\times x_2^2x_1^{k_1} \\ & \vdots \\ & \times x_2^{k_2} \times x_2^{k_2}x_1 \times x_2^{k_2}x_1^2\times\dots\times x_2^{k_2}x_1^{k_1} \\ & \\ & = P_1 \times P_1x_2^{k_1+1} \times P_1\left(x_2^{k_1+1}\right)^2 \times \dots \times P_1\left(x_2^{k_1+1}\right)^{k_2} \\ & = \prod_{j=0}^{k_2}\left(P_1\left(x_2^{k_1+1}\right)^j\right)\text{.} \end{aligned}

Generalizando a PiP_i, tenemos

Pi=j=0ki(Pi1(xiCi1)j). P_i = \prod_{j=0}^{k_i}\left(P_{i-1}\left(x_i^{C_{i-1}}\right)^j\right)\text{.}

La aparición de Ci1C_{i-1} en lugar de ki1+1k_{i-1} + 1 se debe a que necesitamos dar a todos los Ci1C_{i-1} divisores previos un multiplicador de xijx_i^j. Simplificando, tenemos

Pi=j=0ki(Pi1(xiCi1)j)=Pi1ki+1j=0ki((xiCi1)j)=Pi1ki+1(j=0kixij)Ci1=Pi1ki+1(xij=0kij)Ci1=Pi1ki+1(xiki(ki+1)/2)Ci1, \begin{aligned} P_i & = \prod_{j=0}^{k_i}\left(P_{i-1}\left(x_i^{C_{i-1}}\right)^j\right) \\ & = P_{i-1}^{k_i+1}\prod_{j=0}^{k_i}\left(\left(x_i^{C_{i-1}}\right)^j\right) \\ & = P_{i-1}^{k_i+1}\left(\prod_{j=0}^{k_i}x_i^j\right)^{C_{i-1}} \\ & = P_{i-1}^{k_i+1}\left(x_i^{\sum_{j=0}^{k_i}j}\right)^{C_{i-1}} \\ & = P_{i-1}^{k_i+1}\left(x_i^{k_i(k_i+1)/2}\right)^{C_{i-1}}\text{,} \end{aligned}

que es la recurrencia deseada. Notar que C1=k1+1C_1 = k_1 + 1.

#include <bits/stdc++.h> typedef long long ll; using namespace std; const ll MOD = 1e9 + 7; ll expo(ll base, ll pow) { ll ans = 1; while (pow) { if (pow & 1) ans = ans * base % MOD; base = base * base % MOD; pow >>= 1; } return ans; } ll p[100001], k[100001]; int main() { cin.tie(0)->sync_with_stdio(0); int n; cin >> n; for (int i = 0; i < n; i++) cin >> p[i] >> k[i]; ll div_cnt = 1, div_sum = 1, div_prod = 1, div_cnt2 = 1; for (int i = 0; i < n; i++) { div_cnt = div_cnt * (k[i] + 1) % MOD; div_sum = div_sum * (expo(p[i], k[i] + 1) - 1) % MOD * expo(p[i] - 1, MOD - 2) % MOD; div_prod = expo(div_prod, k[i] + 1) * expo(expo(p[i], (k[i] * (k[i] + 1) / 2)), div_cnt2) % MOD; div_cnt2 = div_cnt2 * (k[i] + 1) % (MOD - 1); } cout << div_cnt << ' ' << div_sum << ' ' << div_prod; return 0; }