Mais recursão ainda AULA 4. Máximo divisor comum. Divisibilidade. Máximo divisor comum. Divisibilidade PF 2.1, 2.2, 2.3 S 5.1

Documentos relacionados
AULA 4. Algoritmo de Euclides. Hoje. Algoritmo de Euclides. Correção. Euclides recursivo

Hoje. mais análise de algoritmos: algoritmo de Euclides mais recursão: curvas de Hilbert

AULA 24. Algoritmos p.856/905

AULA 17. Melhores momentos. Segmento de soma máxima. Segmento de soma máxima. Conclusões. Algumas técnicas

INE5403 FUNDAMENTOS DE MATEMÁTICA DISCRETA

Recursividade. Estrutura de Dados. Prof. Kleber Rezende

Programação Estruturada

Recursão. Prof. Fabrício Olivetti de França. (com inspirações do slide do prof. Rodrigo Hausen)

Melhores momentos AULA 1. Algoritmos p.38/86

Complexidade de Algoritmos

AULA 19 AULA 20. Ordenação: algoritmo Quicksort. Resumo. Melhores momentos

Introdução aos números inteiros

if not(isinstance(a, int)) or a < 0: raise ValueError ( misterio: arg devia ser inteiro nao negativo ) else: return misterio_aux(a, a + 1)

Medida do Tempo de Execução de um Programa. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR

Introdução à Análise de Algoritmos

if not(isinstance(a, int)) or a < 0: raise ValueError ("misterio: arg nao e inteiro nao negativo") else: return misterio_aux(a, a + 1)

controle de fluxo repetições iterativas

5 Congruências lineares. Programa. 1 Parte 1 - Conjuntos e Aplicações. 1 Conjuntos. 4 Indução matemática e divisibilidade

Introdução à Teoria dos Números - Notas 4 Máximo Divisor Comum e Algoritmo de Euclides

Invariantes de Laço. Profa. Sheila Morais de Almeida. junho DAINF-UTFPR-PG

Definição. Diremos que um número inteiro d é um divisor de outro inteiro a, se a é múltiplo de d; ou seja, se a = d c, para algum inteiro c.

Aula 18 Algoritmos básicos de busca e classificação

Técnicas de análise de algoritmos

Técnicas de projeto de algoritmos: Indução

Estrutura de Dados Conceitos Iniciais

Recursão. Aula 1. Liana Duenha. Faculdade de Computação Universidade Federal de Mato Grosso do Sul

Análise de algoritmos

Aula 21 - Algoritmos e Funções Recursivas

AED2 - Aula 11 Problema da separação e quicksort

Capítulo 3: Repetições. Pontifícia Universidade Católica Departamento de Informática

Recursão David Déharbe

MC102 Algoritmos e Programação de Computadores

ALGORITMOS AVANÇADOS UNIDADE II Recursividade. Luiz Leão

INE5403 FUNDAMENTOS DE MATEMÁTICA DISCRETA

INF1005: Programação 1. Repetições. 08/03/10 (c) Paula Rodrigues 1

a = bq + r e 0 r < b.

Busca Binária. Aula 05. Busca em um vetor ordenado. Análise do Busca Binária. Equações com Recorrência

Técnicas de Programação III Análise de Algoritmos (Continuação)

Programação Estruturada Prof. Rodrigo Hausen Recursão

Luís Fernando Schultz Xavier da Silveira. 12 de maio de 2010

Sequências recorrentes e testes de primalidade

CORREÇÃO DE ALGORITMOS E

Prova 1 QUESTÃO 1. (1) nusp % 3 == 1. MAC2166 Introdução à Computação para a Engenharia. # include <stdio.h>

Comportamento assintótico

a = bq + r e 0 r < b.

Algoritmos e Estruturas de Dados I Linguagem C

Bruno Hott Algoritmos e Estruturas de Dados I DECSI UFOP. Recursividade

Algoritmos e Lógica de Programação. 6ª Lista de Exercícios Comandos de Repetição

ANÁLISE DE ALGORITMOS

MATEMÁTICA 1 MÓDULO 2. Divisibilidade. Professor Matheus Secco

I. Correção de Algoritmos Não-Recursivos

Aula prática 5. Funções Recursivas

ALGORITMO DE EUCLIDES

1 Congruências e aritmética modular

Pensamento Recursivo. O Objeto Carro. O Objeto Carro. O Objeto Carro. O Objeto Carro. O Objeto Carro

Primeiro Desao Mestre Kame

Aula 14: Repetição (Parte 2)

Primos... Determinar se um inteiro é primo. 1. Um número é primo se apenas é divisível por ele próprio e por 1.

MC102 Aula 26. Instituto de Computação Unicamp. 17 de Novembro de 2016

Matemática para Ciência de Computadores

Modelagem com relações de recorrência. Exemplo: Determinada população dobra a cada ano; população inicial = 5 a n = população depois de n anos

Aula 03: Análise de algoritmos melhor caso, pior caso e caso médio

03 Análise de Algoritmos (parte 3) SCC201/501 - Introdução à Ciência de Computação II

CIC 111 Análise e Projeto de Algoritmos II

NÚMEROS INTEIROS. Álgebra Abstrata - Verão 2012

Estruturas de Dados, Análise de Algoritmos e Complexidade Estrutural. Carlos Alberto Alonso Sanches

Recursividade. Métodos iterativos. Prof. Cesar Augusto Tacla. Métodos iterativos utilizam estruturas de repetição

Programação I Aula 19 Aritmética com racionais Pedro Vasconcelos DCC/FCUP

SCC Capítulo 2 Recursão

BUSCA. 4.1 Busca seqüencial

Melhores momentos AULA 3. Algoritmos p.148/188

Aula 05: - Recursão (parte 1)

Algoritmos e Estruturas de Dados I (DCC/003) Estruturas Condicionais e de Repetição

Recursividade. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR

Complexidade de Algoritmos

Prova 1 PMR3201 Computação para Automação 1o. semestre 2016 Prof. Thiago de Castro Martins

EEL470 Algoritmos e Estruturas de Dados Prof. Heraldo L. S. Almeida Prova 1 (22/05/2009)

é uma proposição verdadeira. tal que: 2 n N k, Φ(n) = Φ(n + 1) é uma proposição verdadeira. com n N k, tal que:

1. O que podemos dizer sobre a imagem da função. f : Z Z, f(x) = x 2 + x + 1?

CES-11. Noções de complexidade de algoritmos. Complexidade de algoritmos. Avaliação do tempo de execução. Razão de crescimento desse tempo.

Estruturas de Repetição

MDC, MMC, Algoritmo de Euclides e o Teorema de Bachet-Bézout

Exame de Programação Imperativa

Portal da OBMEP. Material Teórico - Módulo de Divisibilidade. MDC e MMC - Parte 1. Sexto Ano

Capítulo 6 Análise de Algoritmos Capítulo 6

Aritmética dos Restos. Problemas com Congruências. Tópicos Adicionais

ALGORITMOS E ESTRUTURAS DE DADOS 2011/2012 ANÁLISE DE ALGORITMOS. Armanda Rodrigues 3 de Outubro 2011

Lista de exercícios sobre contagem de operações Prof. João B. Oliveira

Indução Matemática Forte. Raquel de Souza Francisco Bravo de novembro de 2016

MATEMÁTICA MÓDULO 1 TEORIA DOS NÚMEROS 1. DIVISIBILIDADE 1.1. DEFINIÇÃO 1.2. CRITÉRIOS DE DIVISIBILIDADE

PROGRAMAÇÃO DE COMPUTADORES V - TCC Modulo 6 : Funções Escopo de Variáveis: Globais x Locais Aura - Erick

UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO. Prof.ª Danielle Casillo

XIX Semana Olímpica de Matemática. Nível 3. Polinômios Ciclotômicos e Congruência Módulo p. Samuel Feitosa

Lógica de Programação I

Caminho mais curto a partir de um nó Algoritmos de Dijkstra e Bellman-Ford. O problema tem subestrutura óptima

MA14 - Aritmética Lista 1. Unidades 1 e 2

Caminho mais curto a partir de um nó Algoritmos de Dijkstra e Bellman-Ford

Programa Combinatória Aritmética Racional MATEMÁTICA DISCRETA. Patrícia Ribeiro. Departamento de Matemática, ESTSetúbal 2018/ / 52

Estruturas de Repetição

Aula 7 - Mais problemas com inteiros

Transcrição:

Mais recursão ainda AULA 4 PF 2.1, 2.2, 2.3 S 5.1 http://www.ime.usp.br/ pf/algoritmos/aulas/recu.html Máximo divisor comum Divisibilidade Suponha que a, b e d são números inteiros. PF 2.3 S 5.1 http://www.ime.usp.br/ pf/algoritmos/aulas/recu.html http://www.ime.usp.br/ coelho/mac0122-2012/aulas/mdc/ Dizemos que d divide a se a = k d para algum número inteiro k. d a é uma abreviatura de d divide a Se d divide a, então dizemos que a é um multiplo de d. Se d divide a e d > 0, então dizemos que d é um divisor de a Divisibilidade Máximo divisor comum Se d divide a e d divide b, então d é um divisor comum de a e b. Exemplos: os divisores de 30 são: 1, 2, 3, 5, 6, 10, 15 e 30 os divisores de 24 são: 1, 2, 3, 4, 6, 8, 12 e 24 os divisores comuns de 30 e 24 são: 1, 2, 3 e 6 O máximo divisor comum de dois números inteiros a e b, onde pelo menos um é não nulo, é o maior divisor comum de a e b. O máximo divisor comum de a e b é denotado por mdc(a, b). Exemplo: máximo divisor comum de 30 e 24 é 6 máximo divisor comum de 514229 e 317811 é 1 máximo divisor comum de 3267 e 2893 é 11

Máximo divisor comum Problema: Dados dois números inteiros não-negativos a e b, determinar mdc(a, b). Exemplo: máximo divisor comum de 30 e 24 é 6 máximo divisor comum de 514229 e 317811 é 1 máximo divisor comum de 3267 e 2893 é 11 Café com leite Recebe números inteiros não-negativos a e b e devolve mdc(m, n). Supõe m, n > 0. #define min(m,n) ((m) < (n)? (m) : (n)) int mdc(int m, int n) { int d = min(m,n); while (/*1*/ m%d!= 0 n%d!= 0) /*2*/ d--; /*3*/ return d; Passamos agora a vericar a correção do algoritmo. Correção da função = a função funciona = a função faz o que promete. A correção de algoritmos iterativos é comumente baseada na demonstração da validade de invariantes. Estes invariantes são armações ou relações envolvendo os objetos mantidos pelo algoritmo. Eis relações invariantes para a função mdc. Em /*1*/ vale que (i0) 1 d min(m, n), e (i1) m%t 0 ou n%t 0 para todo t> d, e em /*2*/ vale que (i2) m%d 0 ou n%d 0. É evidente que em /*3*/, antes da função retornar d, vale que m%d = 0 e n%d = 0. Como (i1) vale em /*1*/, então (i1) também vale em /*3*/. Assim, nenhum número inteiro maior que o valor d retornado divide m e n. Portanto, o valor retornado é de fato o mdc(m,n). Relações invariantes, além de serem uma ferramente útil para demonstrar a correção de algoritmos iterativos, elas nos ajudam a compreender o funcionamento do algoritmo. De certa forma, eles "espelham" a maneira que entendemos o algoritmo. Invariantes são assim mesmo. A validade de alguns torna a correção do algoritmo (muitas vezes) evidente. Os invariantes secundários servem para conrmar a validade dos principais.

Quantas iterações do while faz a função mdc? Em outras palavras, quantas vezes o comando "d--"é executado? A resposta é min(m,n)-1... no pior caso. Aqui, estamos supondo que m 0 e n 0. Por exemplo, para a chamada mdc(317811,514229) a função executará 317811-1 iterações, pois mdc(317811, 514229) = 1, ou seja, 317811 e 514229 são relativamente primos. Neste caso, costuma-se dizer que o consumo de tempo do algoritmo, no pior caso, é proporcional a min(m, n), ou ainda, que o consumo de tempo do algoritmo é da ordem de min(m, n). A abreviatura de ordem blá é O(blá). Isto signica que se o valor de min(m, n) dobra então o tempo gasto pela função pode dobrar. Conclusões No pior caso, o consumo de tempo da função mdc é proporcional a min(m, n). O consumo de tempo da função mdc é O(min(m, n)). Se o valor de min(m, n) dobra, o consumo de tempo pode dobrar. Algoritmo de Euclides O máximo divisor comum pode ser determinado através de um algoritmo de 2300 anos (cerca de 300 A.C.), o algoritmo de Euclides. Para calcular o mdc(m, n) o algoritmo de Euclides usa a recorrência: mdc(m, 0) = m; mdc(m, n) = mdc(n, m%n), para n > 0. Assim, por exemplo, mdc(12, 18) = mdc(18, 12) = mdc(12, 6) = mdc(6, 0) = 6. Correção Euclides recursivo A correção da recorrência proposta por Euclides é baseada no seguinte fato. Se m, n e d são números inteiros, m 0, n, d > 0, então d divide m e n d divide n e m%n. int euclidesr(int m, int n) { if (n==0) return m; return euclidesr(n, m % n);

Euclides iterativo int euclidesi(int m, int n) { int r; do { r = m % n; m = n; n = r; while (r!= 0); return m; euclidesr(317811,514229) mdc(317811,514229) mdc(514229,317811) mdc(317811,196418) mdc(196418,121393) mdc(121393,75025) mdc(75025,46368) mdc(46368,28657) mdc(28657,17711) mdc(17711,10946) mdc(10946,6765) mdc(6765,4181) mdc(4181,2584) mdc(2584,1597) mdc(1597,987) mdc(987,610) mdc(610,377) mdc(377,233) mdc(233,144) mdc(144,89) mdc(89,55) mdc(55,34) mdc(34,21) mdc(21,13) mdc(13,8) mdc(8,5) mdc(5,3) mdc(3,2) mdc(2,1) mdc(1,0) mdc(317811,514229) = 1. Qual é mais eciente? Qual é mais eciente? meu_prompt>time./mdc 317811 514229 mdc(317811,514229)=1 real 0m0.004s user 0m0.004s meu_prompt>time./euclidesr 317811 514229 mdc(317811,514229)=1 real 0m0.002s user 0m0.000s meu_prompt>time./mdc 2147483647 2147483646 mdc(2147483647,2147483646)=1 real 0m11.366s user 0m11.361s meu_prompt>time./euclidesr 2147483647 2147483646 mdc(2147483647,2147483646)=1 real 0m0.002s user 0m0.000s O consumo de tempo da função euclidesr é proporcional ao número de chamadas recursivas. Suponha que euclidesr faz k chamadas recursivas e que no início da 1a. chamada ao algoritmo tem-se que 0 < n m. Sejam (m, n) = (m 0, n 0 ), (m 1, n 1 ),..., (m k, n k ) = (mdc(m, n), 0), Por exemplo, para m = 514229 e n = 317811 tem-se (m 0, n 0 ) = (514229, 317811), (m 1, n 1 ) = (317811, 196418), (m 2, n 2 ) = (196418, 121393),... =... (m 27, n 27 ) = (1, 0). os valores dos parâmetros no início de cada uma das chamadas da função.

Estimaremos o valor de k em função de n = min(m, n). Note que m i+1 = n i e n i+1 = m i %n i para i=1,2,...,k. Note ainda que para inteiros a e b, 0 < b a vale que a%b < a 2 (verique!). Desta forma tem-se que n 2 = m 1 %n 1 = n 0 %n 1 < n 0 /2 = n/2 = n/2 1 n 4 = m 3 %n 3 = n 2 %n 3 < n 2 /2 < n/4 = n/2 2 n 6 = m 5 %n 5 = n 4 %n 5 < n 4 /2 < n/8 = n/2 3 n 8 = m 7 %n 7 = n 6 %n 7 < n 6 /2 < n/16 = n/2 4 n 10 = m 9 %n 9 = n 8 %n 9 < n 8 /2 < n/32 = n/2 5 Percebe-se que depois de cada 2 chamadas recursivas o valor do segundo parâmetro é reduzido a menos da sua metade. Seja t o número inteiro tal que 2 t n < 2 t+1 Da primeira desigualdade temos que t lg n, onde lg n denota o logaritmo de n na base 2. Da desigualde estrita, concluímos que k 2(t + 1) 1 = 2t + 1 Para o exemplo acima, onde m=514229 e n=317811, temos que 2 lg n + 1 = 2 lg(317811) + 1 < 2 18,3 + 1 < 37,56 e o número de chamadas recursivas feitas por euclidesr(514229,317811) foram 27. Logo, o número k de chamadas recursivas é não superior a 2t + 1 2 lg n + 1. Resumindo, a quantidade de tempo consumida pelo algoritmo de Euclides é, no pior caso, proporcional a lg n. Este desempenho é signicativamente melhor que o desempenho do algoritmo Café com leite, já que a função f(n) = lg n cresce muito mais lentamente que a função g(n) = n. n (int) lg n 4 2 5 2 6 2 10 3 64 6 100 6 128 7 1000 9 1024 10 1000000 19 1000000000 29

Conclusões Conclusões Suponha que m > n. Suponha que m > n. O número de chamadas recursivas da função euclidesr é 2(lg n) 1. O consumo de tempo da função euclidesr é O(lg n). No pior caso, o consumo de tempo da função euclidesr é proporcional a lg n. Para que o consumo de tempo da função euclidesr dobre é necessário que o valor de n seja elevado ao quadrado. Euclides e Fibonacci Demonstre por indução em k que: Se m > n 0 e se a chamada euclidesr(m,n) faz k 1 chamadas recursivas, então m fibonacci(k + 2) e n fibonacci(k + 1).