TFC 2020
Para conferir a prova na íntegra, clique aqui.
Transporte
Comentário escrito por Vitor Veiga
Conhecimento prévio necessário:
Dadas duas capacidades, máxima e mínima, de um trem e
, queremos achar uma nova capacidade máxima
tal que esta vale 30% de
, e dizer se ela é maior que
. Além disso, devemos remover as casas decimais de
para realizar a comparação.
Sendo assim, basta calcular e depois checar se
. Se for, retornamos
, se não, retornamos
. Note que poderiamos declarar
como uma variável do tipo double e depois retirar as casas decimais utilizando a função floor(), porém, se declararmos
como um int, o C++ automaticamente realiza a aproximação para o maior inteiro menor que o número decimal resultante da operação.
Clique aqui para conferir o código
Diária
Comentário escrito por Arthur Lobo
Conhecimento prévio necessário:
Já que a soma de todos os é menor do que
, podemos criar uma lista que guardará quanto custa a diária em cada um dos dias. Sendo Sk o a soma de todos os
, vamos criar um array
, em que
guardará quanto custa a diária do dia
.
Para montar esse array, digamos que a soma dos até o blocos de dias
é
e já montamos a lista até esse bloco (até o dia
). Então se o bloco de dias
tem tamanho
e preço
, então temos que fazer com que todos os valores de
até
sejam P, ou seja,
, para
, e em seguida aumentamos a soma dos
fazendo
.
Agora que já montamos a lista de quanto custa cada diária, sabemos que para responder uma consulta , ou seja, que pergunta qual vai ser o valor total das diárias se ficar hospedado do dia
até o dia
, devemos computar o valor de
. Agora vamos para as parciais.
Vale ressaltar que se deve usar "long long" ao invés de "int" para computar a soma dos valores de . O único motivo pelo qual existem algumas parciais com
é para caso alguém esqueça de usar long long.
Parcial 1 (
)
Como nessa parcial nos temos poucas consultas, podemos responder cada uma delas em .Para uma consulta
, primeiro inicializamos uma variável "int soma = 0", e então computamos a soma das diárias fazendo um for com
indo de
até
, e fazendo
. No final, a variável soma guardará
.
A complexidade ficará por consulta, então no total é
, que é o suficiente.
Parcial 2 (
)
Nessa parcial, o da consulta é sempre
, então só nos importamos com o
, já que o que vamos querer computar é
, ou seja, a soma de um prefixo da lista.
Para responder qual a soma de cada prefixo, vamos criar outro array , em que
vai guardar a soma das diárias até
, ou seja,
, mas como computar esse novo array?
Perceba que sempre temos que , pois
guardá
e depois só adicionamos
. Portanto, começamos com
, e faremos um for com
indo de
até
(nessa ordem), para cada
, faremos
, pois quando estamos em
, já calculamos
.
Agora, para responder uma consulta (já que
), basta imprimirmos
. A complexidade fica
de pré-processamento e
para cada consulta, portando no total fica
.
Parcial 3 e 4 (Sem restrições adicionais)
Diferente da parcial anterior, agora cada consulta vai pedir qual é o valor de , mas como podemos usar o array
para nos ajudar a computar esse valor de forma rápida? Tente imaginar como saber a soma de cada prefixo pode nos ajudar a descobrir a soma desejada.
é
, o problema é que queremos apenas
. Podemos dividir essa soma que forma
em 2 partes:
, mas nós queremos apenas essa segunda parte. Perceba que essa primeira parte é exatamente
, então para conseguirmos a soma desejada, podemos fazer
, já que, como visto a cima, vai sobrar apenas a segunda parte da maneira que dividimos o
.
Agora, para responder uma consulta , basta imprimirmos
. A complexidade fica
de pré-processamento e
para cada consulta, portando no total fica
, que é o suficiente.
Clique aqui para conferir o código
Robô
Comentário escrito por Caique Paiva e Enzo Dantas
Conhecimento prévio necessário:
Primeiro, vamos fazer a subtask 3, ou seja, . Nesse caso, a ideia é simples! Basta fazer uma matriz
, e, supondo que estamos em
, que é inicializada com
, salvamos uma variável auxiliar
, que vai contar a quantidade de obstáculos que já batemos, e dependendo da direção atual, fazemos o seguinte:
- Se estamos andando para a direita, então, se
for um obstáculo, então mudamos a direção para baixo, e fazemos
. Se não, faça
.
- Se estamos andando para baixo, então, se
for um obstáculo, então mudamos a direção para esquerda, e fazemos
. Se não, faça
.
- Se estamos andando para a esquerda, então, se
for um obstáculo, então mudamos a direção para cima, e fazemos
. Se não, faça
.
- Se estamos andando para cima, então, se
for um obstáculo, então mudamos a direção para direita, e fazemos
. Se não, faça
.
Se , então pare de rodar o código, então, a resposta será
.
Perfeito! Agora, vamos melhorar essa solução. Primeiro, para o problema original, temos que , e então não conseguimos nem construir a matriz, pois se não vai dar MLE (Erro no Limite de Memória), então, vamos criar um vetor de set <int> linhas[
] e um vetor de set <int> colunas [
]. Então, se tem um obstáculo em
, fazemos
e
, e então, a ideia é ver que, se estamos na casa
, então, nós vamos andar até chegamos na próxima parede, e aí viramos, ou seja, não precisamos andar as casa uma de cada vez. Logo, vamos mudar nossas condições que fizemos acima. Suponha que estamos em
, que é inicializada com
, temos que
- Se estamos andando para a direita, então, procuramos no set linhas[
] qual é o primeiro obstáculo depois da casa
e na mesma linha que
, ou seja, qual é o primeiro
em linhas[
] com
, e paramos de andar em
, e então basta fazer
, e
, pois batemos em uma parede, e então viramos para baixo (Para achar esse valor, basta olhar o ponteiro linhas[
].upper_bound(
)).
- As ideias são analogas para os outros casos. Se estamos andando para baixo, então, procuramos no set colunas[
] qual é o primeiro obstáculo depois de
, ou seja, qual é o primeiro
em colunas[
] tal que
, e paramos de andar em
, e então basta fazer
e virar para esquerda (Para achar esse valor, basta olhar o ponteiro colunas[
].upper_bound(
)).
- Se estamos andando para a esquerda, então, procuramos no set linhas[
] qual é o primeiro obstáculo depois de
, ou seja, qual é o primeiro
em linhas[
] tal que
, e paramos de andar em
, e então, faça
e virar para cima (Para achar esse valor, basta olhar o ponteiro linhas[
].upper_bound(
) e voltar o ponteiro uma vez).
- Se estamos andando para cima, então, procuramos no set colunas[
] qual é o primeiro obstáculo depois de
, ou seja, qual é o primeiro
em colunas[
] tal que
, e paramos de antar em
, e então, faça
, e vire para a direita (Para achar esse valor, basta olhar o ponteiro colunas[
].upper_bound(
), e voltar o ponteiro uma vez).
Clique aqui para conferir o código
Sobrinhos
Comentário escrito por Enzo Dantas
Conhecimento prévio necessário:
Primeiramente vamos criar um array com os restos de cada pessoa. Mais especificamente, vamos criar um array e dizer que
, tal que % é a função que retorna o resto da divisão entre
e
. Em seguida vamos ordenar esse array em ordem crescente usando a função
. Finalmente, a resposta será o k-ésimo elemento desse array.