Вы находитесь на странице: 1из 8

Problema A Nmeros Perfeitos Nome do arquivo fonte: perfeitos.

{c, cpp} "Se tantos nmeros quanto queiramos comeando da unidade forem dispostos continuamente em proporo dupla, at que a soma de todos se torne um nmero primo, e se esta soma multiplicada pelo ltimo nmero gera um certo nmero, tal nmero ser perfeito." (Euclides, Elementos, IX.36, 300 A.C.). Nesta passagem, Euclides, 300 anos antes de Cristo, nos fala sobre uma relao entre a soma de potncias de 2, nmeros primos e nmeros perfeitos. Traduzindo o que disse Euclides em notao matemtica moderna teramos: Se 1 + 21 + 22 + ... + 2n primo, ento 2n * ( 1 + 21 + 22 + ... + 2n ), perfeito. Em geral, cientistas da computao conhecem muito bem potncias de 2, e at um certo grau nmeros primos. Assim, o objetivo desta questo tornar voc familiar com nmeros perfeitos! Definio: Nmeros perfeitos, deficientes e abundantes. Todo nmero N divisvel por pelo menos 1 e N. Denotemos por s(N) a soma de todos os divisores de N. Se N = pa * qb * ..., onde p, q, ... so todos primos, ento s(N) = (1+ p1 + ... + pa)*(1 + q1 + ... + qb)* ... . N um nmero perfeito se ele igual a soma de seus divisores, incluindo 1 e N. Em outras palavras, N perfeito se s(N) = 2*N. Os nmeros N para os quais s(N) < 2*N so ditos deficientes. Por fim, os nmeros tais que s(N) > 2*N so ditos abundantes. Por exemplo, s(8) = 1 + 2 + 4 + 8 = 15. Logo 8 um nmero deficiente. J, s(12) = 1 + 2 + 3 + 4 + 6 + 12 = 28, o que nos diz que 12 um nmero abundante. E finalmente, 28 um nmero perfeito pois s(28) = 1 + 2 + 4 + 7 + 14 + 28 = 56. Objetivo Para mostrar que voc compreendeu o que so os nmeros perfeitos, deficientes e abundates escreva um programa que dado um nmero inteiro como entrada, informe o que ele . Entrada e Sada Um conjunto de nmeros inteiros, um por linha, cada um entre 1 e 32000 (inclusive). A entrada encerrada pelo nmero 0 (zero). Para cada nmero dado na entrada, deve ser exibida em uma linha isolada a cadeia perfeito, caso o nmero seja perfeito; abundante caso seja abundante; ou deficiente, caso seja deficiente. Exemplo de entrada 8 12 28 0 Exemplo de Saida deficiente abundante perfeito

Problema B O Enigma das Idades Nome do arquivo fonte: idades.{c, cpp } Sou mais velho que voc. Eu tenho o dobro da idade que tu tinhas, quando eu tinha a idade que tu tens. Quando tu tiveres a idade que eu tenho, nossas idades somadas daro 36 anos. Pergunta-se: que idades ns temos hoje? Objetivo Escreva um programa que resolva o problema acima quando, de maneira geral, substituem-se: o dobro por qualquer mltiplo inteiro 2 M 12, a soma 36 por qualquer inteiro 1 S 300. Entrada A primeira linha da entrada possui um inteiro T (menor que 4000) indicando o nmero de casos de teste na entrada. A seguir so informadas T linhas na entrada, cada uma com um par de inteiros M (2 M 12) e S (1 S 300), de acordo com o significado explicado anteriormente. Sada Para cada caso de teste na entrada, deve ser exibido na sada (seguido de uma linha em branco): Eu = # ano(s) + # dia(s){ + algumas horas} Tu = # ano(s) + # dia(s){ + algumas horas} Substitua os dois # em cada linha respectivamente pela quantidade de anos e dias da idade de eu e tu. Sabe-se que esses nmeros no so maiores que 1000 (mil). Quando restarem algumas horas na idade que no chegam a completar um dia, deve ser impresso na sada ao final da linha + algumas horas (por isso os smbolos de opcional { e } ). Importante: Nos clculos, considere que um ano sempre tem exatos 365 dias e um dia exatas 24 horas (sem passar um segundo sequer). Exemplo de entrada 4 22 23 4 36 12 295 Exemplo de Saida Eu = 0 ano(s) + 324 dia(s) + algumas horas Tu = 0 ano(s) + 243 dia(s) + algumas horas Eu = 1 ano(s) + 121 dia(s) + algumas horas Tu = 1 ano(s) + 0 dia(s) Eu = 15 ano(s) + 57 dia(s) + algumas horas Tu = 9 ano(s) + 172 dia(s) + algumas horas Eu = 120 ano(s) + 0 dia(s) Tu = 65 ano(s) + 0 dia(s)

Problema C Recurso Nome do arquivo fonte: recursao.{c, cpp } Recurso moleza! Muito moleza mesmo! Vejamos essa funo em portugus estruturado: inteiro f (inteiro a, inteiro b, inteiro c, inteiro d) { se a=0 ou b=0 ou c=0 ou d=0 ento retorne 1 fimse; se a=b=c=d ento retorne 3 fimse; retorne f(a-1, b, c, d) + f(a, b-1, c, d) + f(a, b, c-1, d) + f(a, b, c, d-1) + 1; } Em notao matemtica moderna: f(a,b,c,d) = 3, se a=b=c=d e a0, 1, se a=0 ou b=0 ou c=0 ou d=0, f(a-1,b,c,d) + f(a, b-1, c, d) + f(a,b,c-1,d) + f(a,b,c,d-1) + 1, em caso contrrio

Sabendo que as variveis a, b, c, d variam de 0 a 9 (inclusive 0 e 9), implemente um programa que calcula f(a, b, c, d), qualquer que seja a, b, c, d (de 0 a 9). Entrada A entrada inicia por uma linha contendo um inteiro N (menor que 15000) informando o nmero de casos de teste. A seguir h N linhas com quatro inteiros variando de 0 a 9 (inclusive) em cada linha. Cada linha representa um caso de teste respectivamente com os inteiros a, b, c, d. Sada Para cada caso de teste, deve ser impresso uma linha na sada com o valor de f(a,b,c,d). Utilize a entrada e a sada padro. Exemplo de entrada 5 0000 3333 1234 3210 7845 Exemplo de Saida 1 3 637 1 42251556617

Problema D - Dividindo Bolos Nome do arquivo fonte: bolos.{c, cpp } Todo mundo sabe que um bolo nunca termina. Pense bem: se voc dividir um bolo ao meio e comer a metade, ainda vai restar a metade. Essa metade ainda pode ser dividida ao meio de novo e sempre vai sobrar uma metade para dividir. Assumindo como verdadeira essa incrvel informao puramente cientfica que bolos no terminam jamais (e o problema sempre esteve em sua forma justa de dividi-los), ajude um grupo de amigos a dividir um bolo. As regras so simples. Um deles comea e divide pela primeira vez. Da ele fica com a metade do bolo para si e d a outra metade do bolo para todos os outros amigos que tm a primeira letra de seus nomes igual ltima letra do nome dele. Os membros desse segundo grupo tambm dividem a parte que coube a eles pela metade e a comem juntos. A outra metade dada para os outros amigos que ainda no receberam bolo e que tm a ltima letra de seus nomes igual primeira letra de algum membro desse grupo. Esse processo continua at que no reste mais ningum para entregar o bolo pela regra da primeira e ltima letras. Essa ensima-metade do bolo que sobra (sem dono aparente) entregue queles que so chamados de pseudo-amigos. Os pseudo-amigos so todos os amigos que por acaso ainda no tenham recebido bolo at essa ltima diviso. Esses comem o que restou e no dividem pela metade com mais ningum. Pode ser que no haja pseudo-amigos no caso de todos j terem recebido bolo (caso em que todos esto alimentados e ainda sobra bolo!). A primeira diviso do bolo numerada como 1 (assim, apenas um felizardo ganha bolo na diviso 1). Todos os que ganham bolo desse primeiro amigo fazem parte da diviso do bolo 2 e assim por diante. No caso particular de haver pseudo-amigos (conforme descrito anteriormente), convenciona-se que esses fazem parte da diviso 0 (zero). O objetivo desse problema simular o processo de diviso do bolo, informando o nmero de diviso de cada um dos amigos envolvidos. Entrada e Sada A entrada formada por vrios casos de teste. Cada um deles inicia por uma linha contendo um inteiro N (0<N<101) informando o nmero de amigos daquele caso. A seguir, so informadas N linhas com os nomes dos amigos. Todo nome composto por at 20 letras minsculas (de a-z). A entrada termina quando N for informado igual a 0 (zero). O primeiro amigo informado na entrada o felizardo a dividir o bolo primeiro. Para cada caso de teste na entrada, deve ser informada na sada N linhas contendo respectivamente o nmero de diviso do primeiro amigo informado na entrada, depois do segundo amigo e assim por diante. Imprima uma linha em branco ao final de cada caso. Exemplo de entrada 2 ivo luciano 6 carlos alexandrecesarm anselmopaiva maria mario simara 0 Exemplo de Saida 1 0 1 3 3 4 4 2

Problema E - Bug no Caixeiro Viajante Nome do arquivo fonte: tsp.{c, cpp } O caixeiro viajante (ou TSP, de traveling salesman problem) um clssico problema NPCompleto. Dados como entrada N pontos no plano cartesiano, o problema consite em encontrar o ciclo completo de custo mnimo. Um ciclo completo equivale a visitar todos os N pontos, iniciando em um ponto P qualquer e finalizando nesse ponto P, tendo visitado todos os outros N-1 pontos. O custo de se deslocar de um ponto para outro igual distncia euclidiana entre esses dois pontos. O custo total do ciclo completo o somatrio das distncias entre os pontos na ordem em que eles foram visitados. Nota-se que a ordem em que os pontos so visitados interferem no custo total do ciclo. Sem usar de nenhuma heurstica, h da ordem de N! (N fatorial) caminhos diferentes que devem ser testados a fim de se descobrir o custo mnimo. O primeiro impulso de um estudante de computao tentar resolver o problema com o algoritmo: 1) Inicia-se visitando um ponto P qualquer; 2) A varivel SOMA representa o custo total do ciclo. Ela iniciada igual a zero; 3) A varivel V indica o ponto sendo visitado no passo atual. V inicia igual ao ponto P; 4) O prximo ponto a ser visitado o ponto Q, ainda no-visitado, mais prximo de V; 5) Adiciona-se varivel SOMA a distncia entre os pontos V e Q; 6) Atribui-se ao ponto V o ponto Q; 7) O processo continua do passo 4 at que todos os pontos tenham sido visitados; 8) Adiciona-se varivel SOMA a distncia entre P e V. Sua tarefa implementar uma soluo do caixeiro viajante fazendo uso desse algoritmo (que evidentemente no minimiza o custo sempre). Duas consideraes importantes: no passo 1, o critrio para escolher o ponto P deve ser simular o algoritmo com todos os N pontos e dar como resposta a menor SOMA encontrada; no passo 4, caso haja dois ou mais pontos empatados com a menor distncia, o ponto Q a ser escolhido deve ser aquele entre eles que aparecer primeiro na entrada. Frmula A distncia euclidiana D entre dois pontos A(Xa, Ya) e B(Xb, Yb) quaisquer dada pela frmula: D = sqrt[ ( X a X b )2 + (Y a Y b )2 ] Entrada e Sada A entrada composta por vrios casos de teste. Cada caso de teste incia por uma linha contendo um inteiro N (0<N<101). A entrada termina quando N for informado igual a 0(zero). A seguir, h N linhas contendo um par de inteiros cada uma (variando de -2000 a 2000) indicando as coordenadas dos pontos respectivamente nos eixos X e Y Para cada caso de teste, deve ser exibida uma linha na sada com o custo total mnimo de acordo com o algoritmo dado e com duas casas decimais de preciso. Exemplo de entrada 4 00 05 50 55 0 Exemplo de Saida 20.00

Problema F Macacos e Bananas Nome do arquivo fonte: macacos.{c, cpp} Uma das competies mais famosas das Olmpiadas da Floresta a corrida de bananas. O objetivo dos competidores, que so chamados de macacos-atletas, comer o mximo possvel de bananas pulando de bananeira em bananeira. Os macacos-atletas s podem se mover de cada bananeira-pai para qualquer uma de suas respectivas bananeiras-filho. Algumas bananeiras no possuem filhos e so chamadas de bananeiras-folhas. Note que toda bananeira possui uma nica bananeira-pai, a exceo da bananeira onde o macaco comea a competio, que chamada de bananeira-raiz. Sempre que um macaco-atleta visita uma bananeira, ele come todas as suas bananas. Dada essa definio, sua tarefa informar o mximo de bananas que um macaco-atleta pode comer iniciando na bananeira-raiz e terminando em qualquer uma das bananeiras-folhas. Entrada de Dados A entrada inicia por uma linha contendo um inteiro T (menor que 500) indicando o nmero de casos de teste. Cada um dos T casos de teste so representados por P linhas, onde P a maior distncia da bananeira-raiz at uma bananeira-folha. Na primeira linha de cada caso de teste representada a bananeira-raiz, a qual chamaremos de bananeira de nvel 1. Na segunda linha so representadas as bananeiras-filhas da bananeira-raiz, ou seja, as de nvel 2. Na terceira linha so representadas as bananeiras de nvel 3, ou seja, as bananeiras-filhas das bananeiras de nvel 2. Isso segue at as bananeiras de nvel P. Em cada linha, aparecem em ordem as bananeiras-filhas da primeira bananeira que aparece na entrada no nvel imediatamente anterior, depois as bananeiras-filhas da segunda bananeira e assim por diante. Nenhum caso de teste possui mais do que 500 bananeiras no total. Finalmente, cada bananeira representada na entrada por um par de inteiros B e F indicando, respectivamente, o nmero de bananas naquela bananeira e sua quantidade de bananeiras-filho. O exemplo de entrada abaixo apresentado graficamente a seguir (o nmero a quantidade de bananas). Sada de Dados Para cada caso de teste na entrada, deve ser exibido na sada Case #: MAX, onde # o nmero do caso de teste, variando de 1 a T; e MAX o mximo de bananas que um macaco-atleta capaz de comer naquele respectivo caso de teste. Exemplo de entrada 1 13 223141 80706050 Exemplo de Saida Case 1: 11

Problema G SmallF*ck Nome do arquivo fonte: smallfck.{pas, c, cpp } Imagine voc escrever programas em uma linguagem de programao que possui apenas alguns comandos extremamente simples, cada um deles representados por apenas um caracter. Um exemplo a linguagem criada por Urban Mller em 1993, inspirada na linguagem P prime prime (P'') de Corrado Bhm (1964), e batizada de brainf*ck. Na linguagem brainf*ck h apenas oito comandos. Estes so listados abaixo. Um programa uma seqncia desses comandos, possivelmente intercalados com quaisquer outros caracteres que so ignorados. Os comandos so executados sequencialmente. O modelo computacional utilizado bastante simples e consiste em: um programa, um array de 30000 clulas (cada uma com 1 byte de tamanho), todas inicialmente com o valor zero, um ponteiro para o array, inicialmente apontando para o byte mais esquerda do array, dois fluxos de bytes, um para entrada e outro para sada (frequentemente conectados ao teclado e o monitor respectivamente, e utilizando ASCII como codificao). Os oitos comandos de brainf*ck, cada um representado por apenas um nico caracter, so: Comando > < + . , [ ] Significado incrementa o ponteiro do array que passa a referenciar a prxima clula a direita decrementa o ponteiro do array que passa a referenciar a clula imediatamente a esquerda incrementa em 1 o valor do byte atualmente referenciado pelo ponteiro do array decrementa em 1 o valor do byte atualmente referenciado pelo ponteiro do array imprime no fluxo de sada o valor do byte atualmente referenciado pelo ponteiro do array l um byte da entrada armazenando-o na clula atualmente referenciada pelo ponteiro do array pula para o primeiro comando aps o fecho ']' correspondente se o byte atualmente referenciado pelo ponteiro do array for zero, seno executa o comando imediatamente aps '[' pula de volta para o abre '[' correspondente ( no programa [+[]], o primireiro '[' corresponde ao ltimo ']' e o segundo '[' corresponde ao primeiro ']' )

Um exemplo de programa brainfuck ",[.[-],]". Este programa, a exemplo do comando 'cat' do unix, l um byte do fluxo de entrada (primeiro ','); se o valor lido no zero imprime o byte lido no fluxo de saida (comando '.' aps o primeiro '['), seno (se o valor lido zero), termina o programa (pulando para o fim aps o segundo fecha ']' que corresponde ao primeiro '['). Aps imprimir o byte lido, h um lao [-] cuja funo zerar o valor lido. E seguida um novo byte lido (segundo ',') e volta-se (ltimo ']') a testar o valor lido (primeiro '['). Note-se que nesse programa, o ponteiro do array no modificado (no h comandos '<' ou '>'). Objetivo O seu objetivo escrever um programa interpretador para uma variante de brainfuck conhecida como smallf*ck. Na smallf*ck no h comandos de entrada '.' e sada ',' e o array interno binrio (suas clulas armazenam apenas um bit ao invs de um byte). Alm disso as operaes '+' e '-' so

substitudas por um nico operador '*' que inverte o bit ( *0 = 1 e *1 = 0) na posio corrente do ponteiro do array. Em suma, as oito operaes de brainfuck so reduzida a apenas cinco em smallf*ck: '>', '<', '*', '[', ']'. Se um programa tenta mover o ponteiro do array para a esquerda da primeira clula, ou para a direita da ltima clula, ele termina imediatamente. Uma vez que entrada e sada no so definidas, assume-se que a entrada codificada no estado inicial do array binrio e que a sada deve ser decodificada do estado final do array. O array interno, ao invs de 30000 clulas deve conter apenas 16 clulas. Entrada e Sada Como entrada, o seu interpretador deve aceitar um programa smallf*ck e um nmero natural em hexadecimal (4 algarismos) cuja representao em binrio (16 bits) o estado inicial do array interno. Como sada deve ser impresso um nmero hexadecimal (4 algarismos) correspondente ao nmero em binrio presente no estado final do array interno. Importante: tanto o nmero em hexadecimal de entrada quanto o de sada devem ser nmeros escritos com exatos 4 dgitos (com zeros esquerda quando necessrio) variando na faixa de 0000 a ffff. Por exemplo, caso o nmero natural na entrada seja por exemplo '009f' o estado inicial do array interno ser: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 1 Por fim, um arquivo de testes ir conter vrios pares de linhas, a primeira contendo um programa e a segunda o nmero hexadecimal acima descrito. Leia e processe todos os pares de linhas at encontrar fim de arquivo. Para cada par processado, exiba na sada o estado final do array interno em hexadecimal conforme descrito acima. Entrada *[>*] 009f [<][[*]] 58ec <<<[[>]]** cde7 [*] f92e **[>] 500d Saida ff1f 58ec cde7 792e 500d