Soluciones técnicas para el examen de certificación GESP Nivel 3

Impresión de patrones numéricos

Este problema requiere generar una representación visual de dígitos (0-3) en una cuadrícula de 5 capas. La clave es descomponer la estructura de cada número y almacenarla en una matriz para facilitar su acceso según el dígito procesado.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

string representacion[5][4]; 
string filas_base[5] = {
    "#.....****...........",
    "#.***.****.****.****.",
    "#.***.****...........",
    "#.***.****..********.",
    "#.....****..........."
};

int main() {
    // Fragmentar la cadena base en bloques de 5 caracteres para cada número
    for (int capa = 0; capa < 5; ++capa) {
        for (int num = 0; num < 4; ++num) {
            representacion[capa][num] = filas_base[capa].substr(num * 5 + 1, 5);
        }
    }

    int valor;
    cin >> valor;
    vector<int> digitos;
    if (valor == 0) digitos.push_back(0);
    while (valor > 0) {
        digitos.insert(digitos.begin(), valor % 10);
        valor /= 10;
    }

    for (int f = 0; f < 5; ++f) {
        for (int d : digitos) {
            cout << representacion[f][d];
        }
        cout << endl;
    }
    return 0;
}

Sustitución condicional de valores

Para optimizar este problema, evitaoms el ordenamiento (O(N log N)) y optamos por una búsqueda lineal (O(N)) de los valores extremos. Posteriormente, se realiza una comparación directa con el umbral proporcionado.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int n, k;
    if (!(cin >> n >> k)) return 0;
    vector<int> lista(n);
    int val_max = -2e9, val_min = 2e9;

    for (int i = 0; i < n; ++i) {
        cin >> lista[i];
        if (lista[i] > val_max) val_max = lista[i];
        if (lista[i] < val_min) val_min = lista[i];
    }

    for (int i = 0; i < n; ++i) {
        if (lista[i] > k) cout << val_max << " ";
        else if (lista[i] == k) cout << k << " ";
        else cout << val_min << " ";
    }
    return 0;
}

División de cadenas en palíndromos

El objetivo es determinar si una cadena puede dividirse en dos subcadenas, cada una con una longitud mínima de 2, que sean palíndromos. Se itera sobre los posibles puntos de corte y se verifica la simetría de ambas partes.

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

bool esPalindromo(string t) {
    string rev = t;
    reverse(rev.begin(), rev.end());
    return t == rev;
}

int main() {
    int casos;
    cin >> casos;
    while (casos--) {
        string s;
        cin >> s;
        bool posible = false;
        int tam = s.length();
        for (int i = 2; i <= tam - 2; ++i) {
            string parte1 = s.substr(0, i);
            string parte2 = s.substr(i);
            if (esPalindromo(parte1) && esPalindromo(parte2)) {
                posible = true;
                break;
            }
        }
        cout << (posible ? "Yes" : "No") << endl;
    }
    return 0;
}

Verificación de secuencias equilibradas

Utilizando la técnica de sumas acumuladas (Prefix Sums), podemos determinar eficientemente si existe un punto de equilibrio donde la suma de los elementos a la izquierda sea igual a la suma de los elementos a la derecha.

#include <iostream>
#include <vector>

using namespace std;

void resolver() {
    int m;
    cin >> m;
    vector<long long> vec(m + 1);
    long long suma_total = 0;
    for (int i = 1; i <= m; ++i) {
        cin >> vec[i];
        suma_total += vec[i];
    }
    
    long long acumulado = 0;
    bool exito = false;
    for (int i = 1; i <= m; ++i) {
        acumulado += vec[i];
        if (acumulado * 2 == suma_total) {
            exito = true;
            break;
        }
    }
    cout << (exito ? "Yes" : "No") << endl;
}

int main() {
    int t;
    cin >> t;
    while (t--) resolver();
    return 0;
}

Identificación de múltiplos comunes

Este algoritmo identifica el valor máximo de un conjunto y verifica si este es divisible por todos los demás elementos presentes en la secuencia.

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int q;
    cin >> q;
    while (q--) {
        int c;
        cin >> c;
        vector<int> nums(c);
        int tope = 0;
        for (int i = 0; i < c; ++i) {
            cin >> nums[i];
            if (nums[i] > tope) tope = nums[i];
        }
        bool divisible = true;
        for (int x : nums) {
            if (tope % x != 0) {
                divisible = false;
                break;
            }
        }
        cout << (divisible ? "Yes" : "No") << endl;
    }
    return 0;
}

Desplazamiento cíclico de caracteres

Implementación de un cifrado de César básico. Es fundamental aplicar el operador módulo 26 al valor de desplazamiento para manejar rotaciones completas del alfabeto.

#include <iostream>

using namespace std;

int main() {
    int desplazamiento;
    cin >> desplazamiento;
    desplazamiento %= 26;
    for (int i = 0; i < 26; ++i) {
        char original = 'A' + i;
        char transformado = 'A' + (i + desplazamiento) % 26;
        cout << transformado;
    }
    return 0;
}

Conteo de pares con suma de cuadrado perfecto

Precalculamos los cuadrados perfectos dentro del rango máximo posible (200,000 en este caso) utilizando un arreglo booleano para realizar consultas en tiempo constante O(1).

#include <iostream>
#include <vector>

using namespace std;

bool es_cuadrado[200005];

int main() {
    for (int i = 0; i * i <= 200000; ++i) {
        es_cuadrado[i * i] = true;
    }
    int total_n;
    cin >> total_n;
    vector<int> valores(total_n);
    for (int i = 0; i < total_n; ++i) cin >> valores[i];
    
    int pares = 0;
    for (int i = 0; i < total_n; ++i) {
        for (int j = i + 1; j < total_n; ++j) {
            if (es_cuadrado[valores[i] + valores[j]]) {
                pares++;
            }
        }
    }
    cout << pares << endl;
    return 0;
}

Cálculo de suma basada en ASCII

El problema distingue entre letras minúsculas (sumando su posición alfabética) y otros caracteres (restando su valor ASCII decimal).

#include <iostream>
#include <string>

using namespace std;

int main() {
    int longitud;
    string cadena;
    cin >> longitud >> cadena;
    long long resultado = 0;
    for (char c : cadena) {
        if (c >= 'a' && c <= 'z') {
            resultado += (c - 'a' + 1);
        } else {
            resultado -= (int)c;
        }
    }
    cout << resultado << endl;
    return 0;
}

Etiquetas: cpp algoritmos gesp estructuras-de-datos programación-competitiva

Publicado el 6-16 16:59