Editorial for Pares Satisfactorios


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Author: aniervs

Tratemos de iterar por todas los pares (a, b) que son soluciones.

Obviamente b\cdot y < n. Iteremos por todos los posibles valores de b, y para cada b, iteremos por cada posible y, tal que b\cdot y \le n. Para un b fijo, iteramos por \lfloor\frac{n}{b}\rfloor valores de y, por lo cual en total se iteran por \sum_{i=1}^n \lfloor\frac{n}{i}\rfloor = \mathcal{O}(n\cdot \ln n) pares (b,y).

Una vez que b\cdot y está fijo, tenemos que a\cdot x = n - b\cdot y. Si tenemos el valor de a\cdot x, entonces el valor de a puede tomar cualquier divisor de a\cdot x que sea menor que b; podemos iterar por estos divisores y guardar copias únicas en un arreglo, luego añadimos a la respuesta la cantidad de valores distintos de a visitados.

Entonces:

  • primero precomputamos para cada número \le n un vector con sus divisores.
  • Luego iteramos por b: 2 \le b < n; por cada b:
    • iteramos por y \in \left[1,\left\lfloor\frac{n}{b}\right\rfloor\right], y por cada y:
      • tenemos c = n - b\cdot y,
      • iteramos por los divisores a de c hasta que a \ge b.
    • Para un b fijo, marcamos los valores de a 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.

Complejidad temporal: Sea D(n) la máxima cantidad de divisores de un número \le n, entonces podemos acotar la complejidad temporal de esta solución a \mathcal{O}(n\cdot \ln n \cdot D(n)). Se puede ver que D(n) \le 180, pero esta cota es mucho mayor que la real, ya que no todos los números tienen D(n) 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

There are no comments at the moment.