Editorial for Pares Satisfactorios
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Tratemos de iterar por todas los pares que son soluciones.
Obviamente . Iteremos por todos los posibles valores de , y para cada , iteremos por cada posible , tal que . Para un fijo, iteramos por valores de , por lo cual en total se iteran por pares .
Una vez que está fijo, tenemos que . Si tenemos el valor de , entonces el valor de puede tomar cualquier divisor de que sea menor que ; podemos iterar por estos divisores y guardar copias únicas en un arreglo, luego añadimos a la respuesta la cantidad de valores distintos de visitados.
Entonces:
- primero precomputamos para cada número un vector con sus divisores.
- Luego iteramos por ; por cada :
- iteramos por , y por cada :
- tenemos ,
- iteramos por los divisores de hasta que .
- Para un fijo, marcamos los valores de que visitamos (
mark[a] = true
), - luego añadimos a la respuesta cuántos valores están marcados;
- por último limpiamos el arreglo con el marcamos los números.
- iteramos por , y por cada :
Complejidad temporal: Sea la máxima cantidad de divisores de un número , entonces podemos acotar la complejidad temporal de esta solución a . Se puede ver que , pero esta cota es mucho mayor que la real, ya que no todos los números tienen divisores.
#include<bits/stdc++.h>
using namespace std;
const int maxn = (int)3e5 + 5;
typedef long long ll;
vector<int> divs[maxn];
bool mark[maxn];
int aux[maxn];
int main() {
ios_base::sync_with_stdio(0); cin.tie(0);
int n;
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = i; j <= n; j+=i){
divs[j].push_back(i);
}
}
ll ans = 0;
for(int b = 2; b < n; b++){
int co = 0;
for(int by = b; by < n; by+=b){
int ax = n - by;
for(int a:divs[ax]){
if(a >= b)
break;
if(!mark[a]){
aux[co++] = a;
mark[a] = 1;
}
}
}
ans += co;
for(int i = 0; i < co; i++)
mark[aux[i]] = 0;
}
cout << ans;
return 0;
}
Comments