Editorial for La progresión armónica
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Queremos resolver . Consideremos
. Entonces queremos resolver
Es bien conocido cómo factorizar esta ecuación, pero igual lo ponemos aquí:
Multiplicando por a ambos lados de la ecuación, obtenemos
, que es lo mismo que
. Restamos
a ambos lados de la ecuación, obteniendo:
Ahora sacamos factor común con los términos
y
, y factor común
con los términos
y
, obteniendo
, luego sacamos factor común una vez más -esta vez sería
-, obteniendo
. Multiplicando por
a ambos lados obtenemos
Queríamos llegar esa factorización. Ahora sustituimos , quedando
, que es lo mismo que
Notemos que es entero, y
y
también lo son. Por tanto,
y
son divisores de
. Entonces, solo debemos considerar las parejas de números
, tales que
, (es decir, los divisores de
), y para cada pareja,
y
toman valores únicos. Si estamos analizando la pareja
, entonces
, y
, por lo que
, y
. Solo contamos los que sean enteros positivos.
Quedan varias cosas por analizar:
La primera es acotar la cantidad de divisores de
. Es bien conocido que la cantidad de divisores de
, para
, es de orden
. Como queremos los divisores de
, y
, tenemos cerca de
divisores en el peor caso, lo cual es suficientemente pequeño.
Bien, ya sabemos cuántos divisores son como mucho. Ahora, cómo iterar por los divisores de
, porque incluso cuando son pocos, iterar por todos los números chequeando si son o no divisores resulta costoso.
Veamos este subproblema de manera más general: Dado , computar los divisores de
. Para hacerlo, consideremos la factorización en primos de
; digamos que
, donde cada
es un primo distinto y cada
es un entero positivo. Cada divisor de
se representa con exactamente los mismos primos de
, y con exponentes no negativos menores o iguales a los exponentes de
. Por tanto, podemos probar todas las combinaciones
, (con
), y para cada combinación generar el número
, el cual es un nuevo divisor de
. Para probar todas las combinaciones podemos hacer backtracking.
- Ahí surge un problema, cómo factorizar
. Es sencillo factorizar
en tiempo
, pero en este caso
. Por suerte, la factorización de
es simplemente la misma factorización de
, solo con los exponentes duplicados. Entonces, podemos factorizar
, lo cual tomaría
operaciones, que si nos podemos permitir.
Resumen:
- El problema se reduce a contar las soluciones enteras
de la ecuación
.
- Hay una correspondencia 1-1 entre las parejas de divisores
de
, y las parejas de soluciones
. Por tanto el problema se reduce a buscar los divisores de
.
- Para hacerlo, factorizamos
, duplicamos todos los exponentes, obtenemos ese arreglo de exponentes
, y hacemos un backtracking probando todos los posibles arreglos de exponentes
, con
para cada
. Para cada uno de esos exponentes, sacamos el divisor resultante, y vemos si conduce a una pareja
válida.
Complejiad temporal: .
Código de ejemplo:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> par;
typedef pair<ll,int> ii;
vector<par> ans;
vector<ii> v;
void factorize(int x){
for(ll i = 2; i*i <= x; i++){
int cnt = 0;
while(x % i == 0){
x /= i;
cnt++;
}
if(cnt > 0) v.push_back({i,2*cnt});
}
if(x > 1) v.push_back({x,2});
}
ll b, n;
void bct(int id, ll d){
if(d > b) return;
if(id == v.size()){
ll p = n/d;
if(d % 2 != b % 2) return;
if(p % 2 != b % 2) return;
ll a = (d + b)/2;
ll c = (p + b)/2;
if(a > c) swap(a,c);
ans.push_back({a,c});
if(a != c) ans.push_back({a,c});
return;
}
bct(id+1,d);
ll cur = 1;
for(int i = 0; i < v[id].second; i++){
cur *= v[id].first;
bct(id+1,d*cur);
}
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> b;
n = b*b;
factorize(b);
bct(0,1);
sort(ans.begin(), ans.end());
cout << ans.size() << '\n';
for(par it:ans)
cout << it.first << ' '<< it.second <<'\n';
return 0;
}
Comments