Comentário Noic OBI 2019 - Fase 1 - Programação Nível 1

Comentário por Lúcio Cardoso

Para conferir a prova na íntegra, clique aqui.

Idade de Dona Mônica

Conhecimento prévio necessário:

Seja C a idade do terceiro filho. Note que A+B+C = M, e logo, C = M-A-B. Assim, o nosso programa deve imprimir o máximo dentre A, B e M-A-B. Para isso, utilizaremos a função max() do C++.

Complexidade: O(1).


// Comentário Noic OBI 2019 - Fase 1 - Programação Nível 1
// Idade de Dona Mônica
#include <bits/stdc++.h>
using namespace std;
int main(void)
{
int m, a, b;
cin >> m >> a >> b;
int c = m-a-b;
// maximo dentre a, b, e c
cout << max(a, max(b, c)) << "\n";
}

Nota Cortada

Conhecimento Prévio Necessário:

Perceba que os dois pedaços resultantes do corte terão o formato de um trapézio. Assim, lembrando que a área de um trápezio de altura h e bases a, b é \frac{h \cdot (a+b)}{2}, teremos que a área da figura mais à esquerda será igual a \frac{70 \cdot (B+T)}{2}. Tendo isso em mente, podemos agora simplesmente checar se a área resultante é maior, igual ou menor que metade da área do retângulo, imprimindo, assim, as respectivas respostas.

Complexidade: O(1).


// Comentário Noic OBI 2019 - Fase 1 - Programação Nível 1
// Nota Cortada
#include <bits/stdc++.h>
using namespace std;
int main(void)
{
int B, T;
cin >> B >> T;
// metade da área do retângulo
int metade = (70*160)/2;
// área do lado esquerdo
int area = (70*(B+T))/2;
if (area == metade) cout << "0\n";
else if (area > metade) cout << "1\n";
else cout << "2\n";
}

Jogo de Dominós

Conhecimento prévio necessário:

Fato 1: O valor da soma 1 + 2 + 3 + ... + N, para um N inteiro, é igual a \frac{N \cdot (N+1)}{2}.

Seja T(x) a quantidade de peças em que um lados tem valor x e o outro lado possui um valor menor ou igual a x. É fácil notar que o total de peças em um jogo duplo-N será igual a T(0) + T(1) + T(2) + ... + T(N). Além disso, podemos notar que T(x) = x+1, já que a quantidade de valores não-negativos menores ou iguais a x é x+1. Assim, a resposta do nosso problema é 1 + 2 + 3 + ... + (N+1), e pelo Fato 1, sabemos que esta soma possui valor igual a \frac{(N+1) \cdot (N+2)}{2}.

Note que o Fato 1 não era necessário para resolver o problema: Poderíamos resolvê-lo usando simplesmente um loop que soma os valores de 1 a N+1 em uma variável que guarda a resposta, com complexidade O(n).

Complexidade: O(1) ou O(n).


// Comentário Noic OBI 2019 - Fase 1 - Programação Nível 1
// Jogo de Dominós
#include <bits/stdc++.h>
using namespace std;
int main(void)
{
int n;
cin >> n;
// 1 + 2 + ... + (N+1)
cout << ((n+1)*(n+2))/2 << "\n";
}

Distância entre amigos

Conhecimento prévio necessário:

Seja H(i) a quantidade de andares no i-ésimo prédio. Pela descrição do problema, temos que a distância entre dois apartamentos i e j (com j  data-recalc-dims= i" />) é igual a H(i) + H(j) + (j-i). Vamos, então, descobrir para cada prédio j (1 \leq j \leq N) a maior distância distância possível para algum prédio com índice menor que j. Pela expressão obtida anteriormente, é fácil notar que o prédio i que dará a maior distância para o prédio j é aquele com valor H(i)-i máximo, já que H(j) e j são valores que independem da escolha de i.

Logo, podemos iterar por cada prédio de 1 a N, e, ao mesmo tempo, usar uma variável maior que guarda o maior valor H(i)-i encontrado até a iteração atual. Assim, a resposta do problema será o valor máximo de H(j) + j + maior, para j = 1, 2, ..., N.

Complexidade: O(N).


// Comentário Noic OBI 2019 - Fase 1 - Programação Nível 1
// Distância entre amigos
#include <bits/stdc++.h>
// valor "infinito"
const int inf = 1e9+10;
using namespace std;
int main(void)
{
int n;
cin >> n;
// inicialmente, maior começa com um valor menor que
// o mínimo valor possível
int maior = -inf;
// resposta do problema
int ans = -inf;
for (int i = 1; i <= n; i++)
{
// altura do i-ésimo prédio
int h;
cin >> h;
// atualizamos a resposta
ans = max(ans, h+i+maior);
// atualizamos o maior valor (H(i)-i)
maior = max(maior, h-i);
}
cout << ans << "\n";
}