OBI 2018 - Fase 3 - Programação Nível 2
Para conferir a prova na íntegra, clique aqui.
Cinco
Comentário por Frederico Bulhões
Conhecimento prévio necessário:
Para resolvermos essa questão devemos observar uma coisa:
- O número inicial dado não é divisível por cinco
- Então para que haja resposta é necessário que a troca ocorra entre um número igual a 0 ou 5 e o número da ultima posição, pois então o novo número terminará em 0 ou 5, tornando-o divisível por cinco.
Como , podemos então fazer um algoritmo em da seguinte forma:
Para todas as posições entre e checamos se o dígito daquela posição é 0 ou 5, caso seja, trocamos ele com o último, e comparamos com a resposta computada até agora, caso maior ele se torna a resposta, e depois trocamos de volta o dígito atual com o último.
Na implementação a seguir é usado a função do C++, que compara lexicograficamente dois vetores passados e retorna o maior.
Clique aqui para conferir o código
Muro
Comentário escrito por Arthur Lobo
Conhecimento prévio necessário:
O problema nos pede de quantas maneiras podemos cobrir um grid (matriz) utilizando dois tipos de tijolos dados. Ele já nos diz a resposta para grids , e , mas como podemos descobrir para um grid maior?
Problemas que perguntam de quantas maneiras conseguirmos cobrir uma matriz com certos tipos de tijolos geralmente usam programação dinâmica (DP). A ideia normalmente é calcularmos a quantidade de maneiras de preenchermos grids de tamanho até , e usar alguns desses valores para computarmos a quantidade para um grid de tamanho .
Vamos definir como quantidade de maneiras de preenchermos um grid com os dois tipos de tijolos. Já sabemos os casos base da nossa DP, pois ele nós dá no enunciado: , , . Agora a ideia será encontrar uma recorrência em que dependa somente de valores menores do que .
Perceba que qualquer muro de tamanho 3 pode ser "desmembrado" em pedaços independentes de tamanhos , ou . Pedaços independentes significam pedaços que contém apenas peças inteiras dentro e não pode ser mais desmembrado em pedaços independentes menores.
Assim como os muros de tamanho 3, muros de quaisquer tamanho maior que 3 também podem ser desmembrados em mais que dois pedaços independentes de tamanhos , ou , então podemos colocar isso na nossa transição da DP!
A ideia será brutar qual vai ser o final do muro e resolver para um muro menor, sendo que já sabemos quais formatos podem estar no final do muro, então podemos apenas testá-los. Para calcular a vamos somar:
- Existe 1 maneira de fazer com que a parede termine com uma peça independente , sobrando .
- Apesar de , existem 4 maneiras de fazer com que a parede termine com uma peça independente , porque uma das 5 de possui duas peças independentes, sobrando .
- Existem 2 maneira de fazer com que a parede termine com uma peça independente , sobrando .
Podemos "testar" qual dos três finais será, então nossa transição será: . Agora basta colocar o módulo nisso e conseguiremos calcular a quantidade de maneiras de construir um grid de tamanho para todo módulo : .
Clique aqui para conferir o código
Baldes
Escrito por Frederico Bulhões
Conhecimento prévio necessário:
Primeiro devemos perceber que para cada balde só importa o menor e o maior valor, e os outros são irrelevantes para a resposta, pois não faz sentido colocar uma bola com o outra de outro balde quando poderíamos pegar uma menor ou maior.
Nesse problema podemos em cada nó da Seg Tree, que representa os baldes entre e , guardar três valores:
- Valor máximo das bolas entre os baldes e , incluso.
- Valor mínimo das bola entre os baldes e , incluso.
- Máximo entre:
- Diferença máxima entre bolas de baldes entre a e de baldes entre e , (sendo ponto do meio entre e );
- Diferença máxima do filho da esquerda, bloco que representa a
- Diferença máxima do filho da direita, bloco que representa a
Podemos então fazer as queries e updates de acordo com a questão, cada uma em , somando u tempo total de
Recibo de Compra
Escrito por Caique Paiva
Conhecimentos Prévios Necessários:
Vamos fazer uma dp! Os estados serão , onde é a quantidade de produtos que precisamos pegar, é o valor total que precisamos pegar, e o valor do último produto que a gente pegou. Então, a transição da dp vai ser
Veja que, se fizéssemos uma knapsack normal, ou seja, só com os estados e tentassemos aplicar a mesma recorrência, teríamos:
Nós retornaríamos com a solução do problema, só que com ordem dos valores importando, ou seja, a escolha de valores seria igual a , e além disso, poderíamos ter valores iguais. Por isso, colocamos o estado na dp, pois, além de garantir que não tenha valores iguais na compra, deixa as escolhas dos valores em ordem crescente, e então, não ocorre repetição.
No final, basta retornar . Essa dp roda em , pois temos estados, e a transição roda em . Isso passa no problema, visto que são bem pequenos.
Bônus: Um problema parecido com esse é o Coin Combinations do cses, vale a pena dar uma olhada! (Link).
Mancha
Comentário escrito por Frederico Bulhões
Conhecimento prévio necessário:
Para resolver esse problema devemos fazer a seguinte observação:
- Caso então para algum ponto na mesma linha ou coluna que o , é verdade que .
- Com isso podemos fazer uma busca, em cada linha ou coluna, vendo se existe um buraco nela. Sendo um buraco um quadrado que não faz parte da mancha, mas que para cima e pra baixo, ou pra esquerda e direita, tenha algum ponto que faz parte da mancha. Pois a distância entre esses pontos, será maior que a distância de manhattan, pois teremos que dar uma volta.
Então podemos escrever uma solução em para resolver esse problema, passando por cada linha e cada coluna checando essa condição em .
Nessa implementação checamosse a soma de pontos que são da mancha entre o primeiro e ultimo daquela linha/coluna é igual a distância entre o primeiro e o último. Caso sim para toadas as linhas e colunas a resposta é sim. Senão a resposta é não.
Clique aqui para conferir o código
Bolas
Comentário escrito por Frederico Bulhões
Conhecimento prévio necessário
Para resolver esse problema podemos usar o Pricípio da Casa dos Pombos. Caso tenhamos um valor com mais de 4 ocorrências, então obrigatoriamente vamos ter que colocar uma dessas bola do lado da outra igual. Para resolver esse problema basta checar essa condição, pois caso ela ocorra, só pode ocorrer com uma bola de um valor.
O código resultante tem complexidade de .