Análise pós-concurso do AtCoder Beginner Contest 383

Problema A
A solução é uma simulação direta. Não há grandes complicações.

int main() { int linhas, colunas; cin >> linhas >> colunas; vector grade(linhas); for (int i = 0; i < linhas; i++) cin >> grade[i];

int contador = 0;
for (int i = 0; i < linhas; i++) {
    for (int j = 0; j < colunas; j++) {
        if (grade[i][j] == '.') {
            // Lógica de contagem baseada na simulação
            contador++;
        }
    }
}
cout << contador << endl;
return 0;

}


</details>**Problema B**  
O ponto crucial é que as células umidificadas não precisam estar conectadas ao umidificadro. A abordagem é enumerar todas as pares possíveis de posições para os dois umidificadores e calcular, para cada par, quantas células são atingidas. A complexidade de tempo é O(h³ \* w³).

<details><summary>Clique para ver o código</summary>```
#include<iostream>
#include<vector>
#include<string>
#include<cstring>
using namespace std;

const int MAX_DIM = 10;
int altura, largura, alcance;
char mapa[MAX_DIM][MAX_DIM];
bool coberto[MAX_DIM][MAX_DIM];
int dirs_x[] = {0, 1, -1, 0, 0};
int dirs_y[] = {0, 0, 0, 1, -1};

int calcularCobertura(int origem_x, int origem_y) {
    int contagem = 0;
    for (int i = 1; i <= altura; i++) {
        for (int j = 1; j <= largura; j++) {
            if (!coberto[i][j] && mapa[i][j] != '#' && abs(i - origem_x) + abs(j - origem_y) <= alcance) {
                coberto[i][j] = true;
                contagem++;
            }
        }
    }
    return contagem;
}

int main() {
    cin >> altura >> largura >> alcance;
    for (int i = 1; i <= altura; i++)
        for (int j = 1; j <= largura; j++)
            cin >> mapa[i][j];

    int maximo = 0;
    for (int ux1 = 1; ux1 <= altura; ux1++) {
        for (int uy1 = 1; uy1 <= largura; uy1++) {
            if (mapa[ux1][uy1] == '#') continue;
            for (int ux2 = 1; ux2 <= altura; ux2++) {
                for (int uy2 = 1; uy2 <= largura; uy2++) {
                    if (ux2 == ux1 && uy2 == uy1) continue;
                    if (mapa[ux2][uy2] == '#') continue;
                    memset(coberto, 0, sizeof(coberto));
                    int total = calcularCobertura(ux1, uy1) + calcularCobertura(ux2, uy2);
                    maximo = max(maximo, total);
                }
            }
        }
    }
    cout << maximo << endl;
    return 0;
}

struct Posicao { int x, y, passos; bool operator<(const Posicao& outro) const { return passos < outro.passos; // Para max-heap } };

int main() { int linhas, colunas, max_passos; cin >> linhas >> colunas >> max_passos; vector grid(linhas); for (int i = 0; i < linhas; i++) cin >> grid[i];

vector<vector<bool>> visitado(linhas, vector<bool>(colunas, false));
priority_queue<Posicao> fila;

// Inicializa a fila com os pontos iniciais 'H'
for (int i = 0; i < linhas; i++) {
    for (int j = 0; j < colunas; j++) {
        if (grid[i][j] == 'H') {
            fila.push({i, j, max_passos});
        }
    }
}

int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};

while (!fila.empty()) {
    Posicao atual = fila.top();
    fila.pop();

    if (visitado[atual.x][atual.y]) continue;
    visitado[atual.x][atual.y] = true;

    if (atual.passos == 0) continue;

    for (int d = 0; d < 4; d++) {
        int nx = atual.x + dx[d];
        int ny = atual.y + dy[d];
        if (nx >= 0 && nx < linhas && ny >= 0 && ny < colunas &&
            !visitado[nx][ny] && grid[nx][ny] != '#') {
            fila.push({nx, ny, atual.passos - 1});
        }
    }
}

int total_visitado = 0;
for (int i = 0; i < linhas; i++)
    for (int j = 0; j < colunas; j++)
        if (visitado[i][j]) total_visitado++;

cout << total_visitado << endl;
return 0;

}


</details>**Problema D**  
Um problema de contagem simples. Como o número de divisores é 9, e apenas números perfeitos quadrados têm uma quantidade ímpar de divisores, pansa-se em enumerar quadrados perfeitos. No entanto, essa abordagem direta não é viável.  
Para otimizar, observa-se que a maioria desses números é da forma a²b² (onde a ≠ b, e a, b são primos), cujos divisores são a, a², b, b², ab, a²b, ab², a²b².  
Além disso, existem números da forma a⁸ (a primo), cujos divisores são as potências de a de 1 a 8.  
A solução é crivar os números primos e então buscar esses padrões. Os dados de teste mostram que a resposta é relativamente pequena, tornando a abordagem factível.

<details><summary>Clique para ver o código</summary>```
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;

int main() {
    long long limite;
    cin >> limite;
    
    long long raiz_limite = sqrt(limite) + 1;
    vector<bool> eh_primo(raiz_limite + 1, true);
    vector<int> primos;
    
    // Crivo de Eratosthenes
    for (int i = 2; i <= raiz_limite; i++) {
        if (eh_primo[i]) {
            primos.push_back(i);
            for (int j = i * i; j <= raiz_limite; j += i) {
                eh_primo[j] = false;
            }
        }
    }
    
    long long resposta = 0;
    int qtd_primos = primos.size();
    
    // Contagem para números da forma a⁸
    for (int idx = 0; idx < qtd_primos; idx++) {
        long long p = primos[idx];
        if (p * p * p * p * p * p * p * p <= limite) {
            resposta++;
        } else break;
    }
    
    // Contagem para números da forma a²b²
    for (int i = 0; i < qtd_primos; i++) {
        long long p1 = primos[i];
        long long p1_quadrado = p1 * p1;
        for (int j = i + 1; j < qtd_primos; j++) {
            long long p2 = primos[j];
            if (p1_quadrado * p2 * p2 <= limite) {
                resposta++;
            } else break;
        }
    }
    
    cout << resposta << endl;
    return 0;
}

Tags: AtCoder C++ Programação Competitiva Algoritmos Busca em Largura

Publicado em 7-13 02:36