OBI 2021 - Fase 2 Turno B - Programação Nível 1
Para se preparar para a OBI, confira o nosso Roteiro de Estudos, nele você vai encontrar um direcionamento completo de como estudar!
Comentário escrito por Anita Almeida, Leonardo Paes, Lúcio Figueiredo e Pedro Racchetti
Para conferir a prova na íntegra, clique aqui.
Recorde
Conhecimento prévio necessário:
Este problema é bem simples e utiliza apenas a estrutura condicional . Após ler os valores, basta comparar se
é menor que
para determinar se é um recorde mundial, e se
é menor que
para determinar se é um recorde olímpico. Se nenhum dois casos for verdade, basta imprimir
.
A complexidade da solução é . Segue o código para melhor compreensão da solução:
Potência
Conhecimento prévio necessário:
- Estruturas Condicionais
- Loops
- Apenas por curiosidade, Congruências
Como dito pelo enunciado do problema, a potência é composta por um único dígito. Então, supomos que estamos lendo um inteiro . Sabemos que na verdade, queremos
. Portanto, uma maneira simples de fazer isso é a seguinte: Após lermos o inteiro
, utilizaremos a função %
, que nos retornará o número módulo
, ou seja, o resto na divisão por
do número em questão. Note que esse valor sempre será o último dígito do número, ou seja, o dígito das unidades. Valor este que representa a potência do nosso termo. Para eliminarmos o último dígito do número, podemos dividí-lo por 10 e tomar a parte inteira da operação. Em C++,
, já que o operador
obtém a parte inteira da divisão. Essa operação faz exatamente o que nós precisamos.
A complexidade da solução é . Confira o código abaixo para melhor entendimento:
PS.: Caso deseje ver uma explicação detalhada das operações realizadas acima, confira a solução do problema Cálculo rápido abaixo.
Cálculo rápido
Conhecimento prévio necessário:
Para resolver este problema, precisamos pensar em como podemos calcular a soma dos dígitos de um número de forma eficiente. Ou seja, dado um número
, precisamos encontrar cada um dos dígitos de
individualmente; feito isso, é fácil calcular a sua soma.
Algortimo para encontrar os dígitos de 
Para extraírmos cada um dos dígitos de , podemos utilizar o seguinte algoritmo:
- Encontre o último dígito
de
;
- Remova o dígito
de
. Denote o número resultante por
;
- Se
não possuir dígito algum, termine o algoritmo. Senão, repita o passo 1 com o novo número
.
Apesar do algoritmo acima estar correto, ainda é necessário descobrir como calcular o último dígito de e como removê-lo.
Encontrar o último dígito de 
Seja o quociente e
o resto na divisão de
por
. Com esta definição, temos que
. Observe que como
é um múltiplo de
, o seu último dígito é igual a
. Além disso, como
é o resto da divisão de
por
, temos que
. Portanto, podemos concluir que o valor
é igual ao último dígito de
em sua representação decimal! Para observar isto, considere os seguintes exemplos:
:
. Último dígito de
é igual a
.
:
. Último dígito de
é igual a
.
:
. Último dígito de
é igual a
.
Com esta observação, concluímos que o último dígito de é igual a
, já que o operador
calcula o resto da divisão de um inteiro por outro.
Remover o último dígito de 
Como é o último dígito de
e
, podemos observar que
é igual ao valor
- ou seja, o valor resultante da remoção do último dígito de
. Novamente, considere os seguintes exemplos para melhor entendimento:
:
.
é igual a
.
:
.
é igual a
.
:
.
é igual a
.
Para encontrar o valor , observe que, por definição, ele é igual a
. Porém, como
, temos que
é igual à parte inteira de
. Portanto, o valor
é igual a
, já que o operador
calcula a parte inteira da divisão.
Agora que sabemos como executar cada passo do algoritmo apresentado acima, basta o utilizarmos para encontrar a soma dos dígitos de .
Complexidade do algoritmo
Observe que a complexidade do algoritmo acima é proporcional à quantidade de dígitos de . Portanto, como a quantidade de dígitos de
é menor ou igual a
, a complexidade final do algoritmo é
.
Etapa final
Agora que possuímos um algoritmo eficiente para encontrar as somas dos dígitos de um número inteiro, o que sobra para terminarmos o problema é executá-lo para cada inteiro entre
e
, utilizando um loop For. Caso a soma dos dígitos de
seja igual a
, adicionamos
em uma variável de resposta, e imprimimos o seu valor ao final do código.
Como executamos o algoritmo acima em todos os números entre e
, a complexidade final da solução é
. Para melhor entendimento, confira o código abaixo:
Lista palíndroma
Conhecimento prévio necessário:
Antes de resolver o problema, podemos fazer algumas observações iniciais. Para uma subarray , com
da lista fornecida, note:
- Se
, então o número de operações necessárias é
;
- Se
, não precisamos fazer uma operação, bastando resolver o problema para a subarray
;
- Se
, precisamos aumentar
. Dessa forma, precisamos fazer uma operação de contração com o consecutivo de
. A mesma ideia se aplica para o caso de
, fazendo a operação entre
e
.
Podemos então usar as observações do algoritmo de Two Pointers indicado no link acima, usando como subarray o intervalo - ou seja, a lista inteira. Usaremos então
como o primeiro ponteiro, começando no início da lista, e
como segundo ponteiro, começando no fim da lista, até que se encontrem pelas operações acima.
A complexidade final da solução é . Segue o código comentado, para melhor compreensão: